import { useState } from 'react'
import { Button } from '../ui/Button'
import { Modal } from '../ui/Modal'
import { ImageGalleryModal } from './ImageGalleryModal'
import { useI18n } from '../../i18n/useI18n'

interface ImageAsset {
  id: string
  asset_type: string
  entity_id: string | null
  still_id: string | null
  episode_id: string | null
  file_path: string
  prompt_used: string | null
  status: string
  is_primary: boolean
  prompt_type: string | null
  created_at: string
  variant_type?: string | null
  is_recommended?: boolean
  recommendation_reason?: string | null
  angle_horizontal?: number | null
  angle_vertical?: number | null
  angle_zoom?: number | null
  color_prompt?: string | null
  selected_for_pdf?: boolean
  parent_image_id?: string | null
  theme_label?: string | null
  source_image_id?: string | null
  generation_model?: string | null
}

interface ResolvedEntity {
  entity_id: string
  entity_name: string
  entity_type: string
  t2i_prompt: string
  has_reference_image: boolean
  reference_image_id: string | null
}

interface SceneStill {
  id: string
  episode_id: string
  still_index: number
  screenplay_scene_heading: string | null
  beat_title: string | null
  still_frame_prompt: string | null
  camera_json: string
  lighting_json: string
  visible_entities_json: string
  t2i_prompt_cinematic: string | null
  t2i_prompt_closeup: string | null
  t2i_variations_json: string | null
  t2i_composer_version: string | null
  variations?: Array<{
    label: string
    type: string
    angle: string | null
    color: string | null
    reason: string | null
  }>
  resolved_entities?: ResolvedEntity[]
  dependent_scenes?: Array<{
    still_id: string
    still_index: number
    beat_title: string
    has_image: boolean
    image_id: string | null
  }>
  start_char?: number | null
  end_char?: number | null
  segment_start_char?: number | null
  segment_end_char?: number | null
  status: string
  created_at: string
}

interface SceneVariationCardProps {
  still: SceneStill
  projectId: string
  images: Record<string, ImageAsset | null>
  allImages: ImageAsset[]  // ALL images for this scene (for dynamic gallery)
  screenplayText?: string | null  // Full screenplay text for segment display
  segmentContextChars?: number    // Context chars before/after segment (default 100)
  onRecommend: () => void
  onGenerate: () => void
  onEditAngle: (imageId: string, h: number, v: number, z: number) => void
  onEditColor: (imageId: string, prompt: string) => void
  onApplyAngleColor: (imageId: string, h: number, v: number, z: number, colorPrompt: string) => void
  onSelectVariant: (variant: string) => void
  onSelectOriginal: (imageId: string) => void
  onEditPrompt: (prompt: string) => void
  onRegenerate?: (imageId: string) => void
  onRemoveEntity?: (entityId: string) => void
  onAddEntity?: (entityId: string) => void
  allEntities?: Array<{ id: string; name: string; entity_type: string }>
  onRemoveDependentScene?: () => void
  onSetDependentScene?: (sceneId: string) => void
  allScenes?: Array<{ id: string; still_index: number; beat_title: string }>
  onSaveT2i?: (promptA: string, promptB: string) => void
  onSetRepresentative?: (imageId: string) => void
  onRegenerateWithPrompt?: (stillId: string, customPrompt: string) => void
  recommendLoading?: boolean
  generateLoading?: boolean
  angleLoading?: boolean
  colorLoading?: boolean
  isGenerating?: boolean
  hasEntityRefs?: boolean
  i2iLoading?: boolean  // loading state for combined angle+color I2I
}

export function SceneVariationCard({
  still,
  projectId,
  images: _images,
  allImages,
  screenplayText,
  segmentContextChars = 100,
  onRecommend: _onRecommend,
  onGenerate,
  onEditAngle: _onEditAngle,
  onEditColor: _onEditColor,
  onApplyAngleColor,
  onSelectVariant: _onSelectVariant,
  onSelectOriginal: _onSelectOriginal,
  onEditPrompt,
  onRegenerate: _onRegenerate,
  onRemoveEntity,
  onAddEntity,
  allEntities = [],
  onRemoveDependentScene,
  onSetDependentScene,
  allScenes = [],
  onSaveT2i,
  onSetRepresentative,
  onRegenerateWithPrompt,
  recommendLoading: _recommendLoading = false,
  generateLoading = false,
  angleLoading = false,
  colorLoading = false,
  isGenerating = false,
  hasEntityRefs = false,
  i2iLoading = false,
}: SceneVariationCardProps) {
  const { t } = useI18n()

  // Accordion sections — images always expanded by default
  const [openSections, setOpenSections] = useState<Set<string>>(new Set(['images']))
  const toggleSection = (s: string) => setOpenSections(prev => {
    const next = new Set(prev)
    if (next.has(s)) next.delete(s); else next.add(s)
    return next
  })

  // Combined gallery modal
  const [modalImage, setModalImage] = useState<ImageAsset | null>(null)

  // Reference entity image zoom modal
  const [refZoomImageId, setRefZoomImageId] = useState<string | null>(null)

  // Screenplay segment collapsed state
  const [segmentExpanded, setSegmentExpanded] = useState(false)

  // Prompt editing
  const [editingPrompt, setEditingPrompt] = useState(false)
  const [promptText, setPromptText] = useState(still.still_frame_prompt || '')

  // Entity add popup
  const [showAddEntity, setShowAddEntity] = useState(false)
  // Dependent scene picker
  const [showDepPicker, setShowDepPicker] = useState(false)

  // T2I prompt editing
  const [editingT2i, setEditingT2i] = useState(false)
  const [t2iA, setT2iA] = useState(still.t2i_prompt_cinematic || '')

  // Sort images: representative (is_primary) first, then by created_at
  const sortedImages = [...allImages].sort((a, b) => {
    if (a.is_primary && !b.is_primary) return -1
    if (!a.is_primary && b.is_primary) return 1
    return a.created_at.localeCompare(b.created_at)
  })

  // Parse prompt markers
  // Supports: [[name]], [[char]+[outlook]]
  const parsePromptMarkers = (prompt: string) => {
    const linked: string[] = []
    const unlinked: Array<{name: string; desc: string}> = []
    // Match [[...]] allowing ]+[ inside for composite markers
    const linkedRegex = /\[\[((?:[^\]]|\](?!\]))+)\]\]/g
    let m: RegExpExecArray | null
    while ((m = linkedRegex.exec(prompt)) !== null) {
      const raw = m[1]
      // Check if it's a composite [[char]+[outlook]] format
      if (raw.includes(']+[')) {
        const parts = raw.split(']+[')
        const charName = parts[0].trim()
        const outlookName = parts[1].trim()
        const composite = `${charName}]+[${outlookName}`
        if (!linked.includes(composite)) linked.push(composite)
      } else {
        if (!linked.includes(raw)) linked.push(raw)
      }
    }
    const unlinkedRegex = /(?<!\[)\[([^\[\]]+?)\s*:\s*([^\]]+)\](?!\])/g
    let m2: RegExpExecArray | null
    while ((m2 = unlinkedRegex.exec(prompt)) !== null) {
      const match = m2
      if (!linked.includes(match[1]) && !unlinked.find(u => u.name === match[1])) {
        unlinked.push({ name: match[1].trim(), desc: match[2].trim() })
      }
    }
    return { linked, unlinked }
  }

  const handleSavePrompt = () => {
    onEditPrompt(promptText)
    setEditingPrompt(false)
  }

  // Extract screenplay segment with configurable context chars
  const getScreenplaySegment = () => {
    const startChar = still.segment_start_char ?? still.start_char
    const endChar = still.segment_end_char ?? still.end_char
    if (!screenplayText || startChar == null || endChar == null) return null
    const ctxBefore = segmentContextChars
    const ctxAfter = segmentContextChars
    const start = Math.max(0, startChar - ctxBefore)
    const end = Math.min(screenplayText.length, endChar + ctxAfter)
    const before = screenplayText.slice(start, startChar)
    const segment = screenplayText.slice(startChar, endChar)
    const after = screenplayText.slice(endChar, end)
    return { before, segment, after }
  }

  const screenplaySegment = getScreenplaySegment()

  return (
    <div className="card" style={{ padding: '18px 20px' }}>
      {/* Still header */}
      <div style={{ display: 'flex', gap: '16px', alignItems: 'flex-start', marginBottom: '12px' }}>
        <div style={{
          width: '36px', height: '36px', background: 'var(--bg-input)',
          borderRadius: 'var(--radius-sm)', display: 'flex', alignItems: 'center',
          justifyContent: 'center', flexShrink: 0, fontFamily: 'var(--font-mono)',
          fontSize: '13px', fontWeight: 700, color: 'var(--text-muted)',
        }}>
          {still.still_index}
        </div>

        <div style={{ flex: 1, minWidth: 0 }}>
          {still.screenplay_scene_heading && (
            <div style={{
              fontFamily: 'var(--font-mono)', fontSize: '12px', color: 'var(--accent)',
              marginBottom: '2px', fontWeight: 600,
            }}>
              {still.screenplay_scene_heading}
            </div>
          )}
          {still.beat_title && (
            <div style={{ fontSize: '14px', fontWeight: 600, fontFamily: 'var(--font-serif)' }}>
              {still.beat_title}
            </div>
          )}
        </div>

        {/* Action buttons — v5: 변형 추천 제거, 생성 버튼만 유지 */}
        <div style={{ display: 'flex', gap: '6px', flexShrink: 0 }}>
          <Button
            size="sm"
            disabled={generateLoading || isGenerating || !hasEntityRefs}
            onClick={onGenerate}
            title={!hasEntityRefs ? t('image.ref_required') : ''}
          >
            {generateLoading || isGenerating ? t('still.generating') : t('still.generate_original')}
          </Button>
        </div>
      </div>

      {/* === Accordion: Content section === */}
      <div onClick={() => toggleSection('content')} style={{
        cursor: 'pointer', padding: '8px 0', display: 'flex', alignItems: 'center', gap: 8,
        fontSize: 13, fontWeight: 600, color: 'var(--text-muted)',
        borderTop: '1px solid var(--border)', marginTop: '4px',
      }}>
        <span>{openSections.has('content') ? '\u25BC' : '\u25B6'}</span>
        {t('still.scene_description') || '\uCF58\uD150\uCE20'}
      </div>
      {openSections.has('content') && (
        <>
          {/* Screenplay segment (collapsible) */}
          {screenplaySegment && (
            <div style={{ marginBottom: '10px' }}>
              <div
                style={{
                  display: 'flex', alignItems: 'center', gap: '6px', cursor: 'pointer',
                  fontSize: '10px', fontWeight: 700, color: 'var(--text-dim)',
                  textTransform: 'uppercase', letterSpacing: '0.04em',
                }}
                onClick={() => setSegmentExpanded(!segmentExpanded)}
              >
                <span>{t('gallery.screenplay_segment')}</span>
                <span style={{ fontSize: '11px', color: 'var(--text-dim)' }}>
                  {segmentExpanded ? '[-]' : '[+]'}
                </span>
              </div>
              {segmentExpanded && (
                <div style={{
                  marginTop: '6px', fontSize: '12px', lineHeight: 1.7,
                  background: 'var(--bg-input)', borderRadius: 'var(--radius-sm)',
                  padding: '10px 14px', border: '1px solid var(--border)',
                  maxHeight: '200px', overflowY: 'auto', fontFamily: 'var(--font-serif)',
                  whiteSpace: 'pre-wrap',
                }}>
                  <span style={{ color: 'var(--text-dim)' }}>{screenplaySegment.before}</span>
                  <span style={{ color: 'var(--text)', background: 'var(--accent-glow)', padding: '0 2px', borderRadius: '2px' }}>
                    {screenplaySegment.segment}
                  </span>
                  <span style={{ color: 'var(--text-dim)' }}>{screenplaySegment.after}</span>
                </div>
              )}
            </div>
          )}

          {/* Scene description (editable) */}
          {still.still_frame_prompt && !editingPrompt && (
            <div
              style={{
                fontSize: '12px', color: 'var(--text-muted)', lineHeight: 1.6,
                background: 'var(--bg-input)', borderRadius: 'var(--radius-sm)',
                padding: '8px 12px', marginBottom: '8px', cursor: 'pointer',
                border: '1px solid transparent',
              }}
              onClick={() => { setEditingPrompt(true); setPromptText(still.still_frame_prompt || '') }}
              onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.borderColor = 'var(--accent)' }}
              onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.borderColor = 'transparent' }}
            >
              <span style={{ fontSize: '10px', fontWeight: 700, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>
                {t('still.scene_description')}
              </span>
              <div style={{ marginTop: '4px' }}>{still.still_frame_prompt}</div>
            </div>
          )}
          {editingPrompt && (
            <div style={{ marginBottom: '8px' }}>
              <textarea
                rows={3}
                value={promptText}
                onChange={(e) => setPromptText(e.target.value)}
                style={{ width: '100%', fontSize: '12px', fontFamily: 'var(--font-mono)' }}
              />
              <div style={{ display: 'flex', gap: '6px', marginTop: '4px' }}>
                <Button size="sm" onClick={handleSavePrompt}>{t('btn.save')}</Button>
                <Button size="sm" variant="ghost" onClick={() => setEditingPrompt(false)}>{t('btn.cancel')}</Button>
              </div>
            </div>
          )}
        </>
      )}

      {/* === Accordion: Scene info section (dependent scenes only — T2I prompt & entities moved to image modal) === */}
      <div onClick={() => toggleSection('prompts')} style={{
        cursor: 'pointer', padding: '8px 0', display: 'flex', alignItems: 'center', gap: 8,
        fontSize: 13, fontWeight: 600, color: 'var(--text-muted)',
        borderTop: '1px solid var(--border)',
      }}>
        <span>{openSections.has('prompts') ? '\u25BC' : '\u25B6'}</span>
        {t('still.dependent_scenes') || '\uC5F0\uAD00 \uC528'}
      </div>
      {openSections.has('prompts') && (
        <>

      {/* Dependent scenes */}
      {(() => {
        const hasDep = still.dependent_scenes && still.dependent_scenes.length > 0
        const currentDepIds = new Set((still.dependent_scenes || []).map((d: any) => d.still_id))
        const availableScenes = allScenes.filter(s => s.still_index < still.still_index && !currentDepIds.has(s.id))

        return (
        <div style={{ marginBottom: '10px' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '4px' }}>
            <span style={{ fontSize: '10px', fontWeight: 700, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>
              {t('still.dependent_scenes')}
            </span>
            {onSetDependentScene && (
              <button
                onClick={() => setShowDepPicker(!showDepPicker)}
                style={{ fontSize: '10px', color: 'var(--accent)', background: 'none', border: 'none', cursor: 'pointer', fontWeight: 600 }}
              >
                {hasDep ? t('gallery.change') : '+ ' + t('gallery.connect')}
              </button>
            )}
          </div>

          {showDepPicker && availableScenes.length > 0 && (
            <div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap', marginBottom: '6px', padding: '6px', background: 'var(--bg-raised)', borderRadius: 'var(--radius-sm)', border: '1px solid var(--accent)' }}>
              {availableScenes.slice(0, 10).map(s => (
                <button
                  key={s.id}
                  onClick={() => { if (onSetDependentScene) { onSetDependentScene(s.id); setShowDepPicker(false) } }}
                  style={{ fontSize: '10px', padding: '2px 8px', background: 'var(--bg-input)', border: '1px solid var(--border)', borderRadius: '999px', cursor: 'pointer', color: 'var(--text-muted)' }}
                >
                  {t('gallery.scene')} {s.still_index}: {s.beat_title?.substring(0, 15)}
                </button>
              ))}
            </div>
          )}

          {hasDep ? (
            <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
              {(still.dependent_scenes || []).map((dep: any) => (
                <div
                  key={dep.still_id}
                  style={{
                    display: 'flex', alignItems: 'center', gap: '4px',
                    padding: '3px 8px', background: 'var(--bg-input)',
                    borderRadius: 'var(--radius-sm)', border: '1px solid var(--accent)',
                    fontSize: '11px',
                  }}
                  title={dep.beat_title}
                >
                  {dep.has_image && dep.image_id ? (
                    <img
                      src={`/api/v1/projects/${projectId}/images/${dep.image_id}/file?thumb=1`}
                      alt={`${t('gallery.scene')} ${dep.still_index}`}
                      style={{ width: '22px', height: '22px', borderRadius: '3px', objectFit: 'cover' }}
                      onError={(e) => { (e.target as HTMLImageElement).style.display = 'none' }}
                    />
                  ) : (
                    <span style={{ width: '22px', height: '22px', borderRadius: '3px', background: 'var(--accent-glow)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '9px', color: 'var(--accent)' }}>#{dep.still_index}</span>
                  )}
                  <span>{t('gallery.scene')} {dep.still_index}</span>
                  {onRemoveDependentScene && (
                    <button
                      onClick={(ev) => { ev.stopPropagation(); onRemoveDependentScene() }}
                      style={{ background: 'none', border: 'none', color: 'var(--text-dim)', cursor: 'pointer', fontSize: '11px', padding: '0 2px' }}
                    >&#x2715;</button>
                  )}
                </div>
              ))}
            </div>
          ) : (
            <span style={{ fontSize: '11px', color: 'var(--text-dim)', fontStyle: 'italic' }}>{t('gallery.none')}</span>
          )}
        </div>
        )
      })()}
        </>
      )}

      {/* === Accordion: Images section (always expanded by default) === */}
      <div onClick={() => toggleSection('images')} style={{
        cursor: 'pointer', padding: '8px 0', display: 'flex', alignItems: 'center', gap: 8,
        fontSize: 13, fontWeight: 600, color: 'var(--text-muted)',
        borderTop: '1px solid var(--border)',
      }}>
        <span>{openSections.has('images') ? '\u25BC' : '\u25B6'}</span>
        {t('gallery.images') || '\uC774\uBBF8\uC9C0'} ({sortedImages.length})
      </div>
      {openSections.has('images') && (
        <>
      <div style={{ marginBottom: '10px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' }}>
          <span style={{ fontSize: '10px', fontWeight: 700, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>
            {t('gallery.images')} ({sortedImages.length})
          </span>
          {isGenerating && (
            <span style={{ fontSize: '11px', color: 'var(--accent)', fontWeight: 600 }}>
              {t('gallery.generating')}
            </span>
          )}
        </div>

        {sortedImages.length === 0 ? (
          <div style={{
            padding: '24px', textAlign: 'center', fontSize: '12px', color: 'var(--text-dim)',
            background: 'var(--bg-input)', borderRadius: 'var(--radius-sm)',
            border: '1px dashed var(--border)',
          }}>
            {t('gallery.no_images')}
          </div>
        ) : (
          <div style={{
            display: 'grid',
            gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',
            gap: '10px',
          }}>
            {sortedImages.map((img) => (
              <div
                key={img.id}
                style={{
                  position: 'relative',
                  borderRadius: 'var(--radius-sm)',
                  overflow: 'hidden',
                  border: img.is_primary
                    ? '2px solid var(--green)'
                    : img.selected_for_pdf
                    ? '2px solid var(--accent)'
                    : '1px solid var(--border)',
                  cursor: 'pointer',
                  transition: 'border-color 0.15s, transform 0.15s',
                }}
                onClick={() => setModalImage(img)}
                onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.transform = 'scale(1.02)' }}
                onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.transform = 'scale(1)' }}
              >
                <img
                  src={`/api/v1/projects/${projectId}/images/${img.id}/file?thumb=1`}
                  alt={img.id}
                  style={{ width: '100%', height: '120px', objectFit: 'cover', display: 'block' }}
                  onError={(e) => { (e.target as HTMLImageElement).style.display = 'none' }}
                />

                {/* Badges overlay */}
                <div style={{
                  position: 'absolute', top: '4px', left: '4px',
                  display: 'flex', flexDirection: 'column', gap: '2px',
                }}>
                  {img.is_primary && (
                    <span style={{
                      fontSize: '9px', padding: '1px 5px',
                      background: 'var(--green)', color: '#fff',
                      borderRadius: '999px', fontWeight: 700,
                    }}>
                      {t('gallery.representative')}
                    </span>
                  )}
                  {img.theme_label && (
                    <span style={{
                      fontSize: '9px', padding: '1px 5px',
                      background: 'rgba(0,0,0,0.6)', color: '#fff',
                      borderRadius: '999px', fontWeight: 600,
                    }}>
                      {img.theme_label}
                    </span>
                  )}
                </div>

                {/* Parent indicator */}
                {img.parent_image_id && (
                  <div style={{
                    position: 'absolute', bottom: '4px', right: '4px',
                    fontSize: '9px', padding: '1px 4px',
                    background: 'rgba(0,0,0,0.5)', color: '#ccc',
                    borderRadius: '999px',
                  }}>
                    {t('gallery.variant')}
                  </div>
                )}

                {/* Variant type badge — v5: theme_label이 있으면 생략 (중복 방지) */}
                {img.variant_type && !img.theme_label && (
                  <div style={{
                    position: 'absolute', bottom: '4px', left: '4px',
                    fontSize: '9px', padding: '1px 4px',
                    background: 'var(--orange-bg, rgba(249,115,22,0.15))', color: 'var(--orange, #f97316)',
                    borderRadius: '999px', fontWeight: 600,
                  }}>
                    {img.variant_type === 'angle' ? t('variation.type.angle')
                      : img.variant_type === 'color' ? t('variation.type.color')
                      : img.variant_type === 'angle_color' ? t('variation.type.angle_color')
                      : img.variant_type}
                  </div>
                )}
              </div>
            ))}
          </div>
        )}
      </div>
        </>
      )}

      {/* Combined Image Gallery Modal */}
      {modalImage && (
        <ImageGalleryModal
          open={!!modalImage}
          image={modalImage}
          projectId={projectId}
          allImages={allImages}
          resolvedEntities={still.resolved_entities || []}
          t2iVariations={(() => {
            try { return JSON.parse(still.t2i_variations_json || '[]') } catch { return [] }
          })()}
          onClose={() => setModalImage(null)}
          onApplyAngleColor={(imageId, h, v, z, colorPromptVal) => {
            onApplyAngleColor(imageId, h, v, z, colorPromptVal)
            // Don't close modal immediately — let loading state show
          }}
          onSetRepresentative={(imageId) => {
            if (onSetRepresentative) {
              onSetRepresentative(imageId)
            }
            setModalImage(null)
          }}
          onRegenerateWithPrompt={onRegenerateWithPrompt}
          loading={i2iLoading || angleLoading || colorLoading}
        />
      )}

      {/* Reference entity image zoom modal */}
      {refZoomImageId && (
        <Modal
          open={!!refZoomImageId}
          title={t('image.zoom')}
          onClose={() => setRefZoomImageId(null)}
          size="large"
        >
          <div style={{ textAlign: 'center' }}>
            <img
              src={`/api/v1/projects/${projectId}/images/${refZoomImageId}/file`}
              alt="reference"
              style={{ maxWidth: '100%', maxHeight: '80vh' }}
            />
          </div>
        </Modal>
      )}
    </div>
  )
}
