import type { ReactNode } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { api, ApiError } from '../api/client'
import { AcIcon } from '../components/AcIcon'
import {
  LeafSparkleArt,
  PassportIslandArt,
  ResearchHutArt,
  StampBellArt,
} from '../components/PersonaIslandArt'
import { Style8DAnalysisMeta } from '../components/Style8DAnalysisMeta'

import { Style8DJobPanel } from '../components/Style8DJobPanel'
import { Style8DDimensionEditor } from '../components/Style8DDimensionEditor'
import {
  AcLink,
  Badge,
  Button,
  Card,
  ErrorText,
  Field,
  Input,
  Notice,
  ProgressBar,
  SuccessText,
  Textarea,
} from '../components/ui'
import { isTerminalJobStatus } from '../lib/jobStatus'
import {
  createEmptyStyle8DProfile,
  parseStyle8DProfile,
  type StoredStyle8DProfile,
  type Style8DKey,
} from '../lib/styleProfile'
import type { JobData, PersonaData } from '../types/api'

const emptyPersona = (): PersonaData => ({
  id: '',
  display_name: '',
  persona: '',
  brief: '',
  style_profile: '',
  style_benchmark: '',
  create_at: 0,
  update_at: 0,
})

function profileCompleteness(draft: PersonaData, has8D: boolean) {
  const fields = [draft.display_name, draft.brief, draft.persona]
  const filled = fields.filter((v) => v?.trim()).length + (has8D ? 1 : 0)
  return Math.round((filled / 4) * 100)
}

function ZoneSign({ children }: { children: ReactNode }) {
  return (
    <div className="ac-persona-sign">
      <StampBellArt className="h-4 w-4 shrink-0 opacity-90" />
      <span>{children}</span>
    </div>
  )
}

export function PersonaDetailPage() {
  const navigate = useNavigate()
  const { id = '' } = useParams()
  const [draft, setDraft] = useState<PersonaData>(emptyPersona())
  const [benchmarkUsername, setBenchmarkUsername] = useState('')
  const [styleResult, setStyleResult] = useState<StoredStyle8DProfile | null>(null)
  const [styleJob, setStyleJob] = useState<JobData | null>(null)
  const [styleJobId, setStyleJobId] = useState<string | null>(null)
  const [loading, setLoading] = useState(true)
  const [busy, setBusy] = useState<string | null>(null)
  const [message, setMessage] = useState('')
  const [error, setError] = useState('')

  const loadPersona = useCallback(async () => {
    if (!id) return
    const data = await api.get<PersonaData>(`/api/v1/personas/${encodeURIComponent(id)}`, { auth: true })
    setDraft({ ...emptyPersona(), ...data })
    setStyleResult(parseStyle8DProfile(data.style_profile))
    setBenchmarkUsername(data.style_benchmark ?? '')
  }, [id])

  const refreshStyleJob = useCallback(
    async (jobId: string) => {
      const job = await api.get<JobData>(`/api/v1/jobs/${encodeURIComponent(jobId)}`, { auth: true })
      if (isTerminalJobStatus(job.status)) {
        setStyleJob(null)
        setStyleJobId(null)
        if (job.status === 'succeeded') {
          await loadPersona()
          setMessage('8D 分析完成，風格策略已寫入人設')
        } else {
          setError(job.error?.trim() || job.progress?.summary || '8D 分析失敗')
        }
        return
      }
      setStyleJob(job)
      setStyleJobId(job.id)
    },
    [loadPersona],
  )

  const loadActiveStyleJob = useCallback(async () => {
    if (!id) return
    const data = await api.get<{ list: JobData[] }>('/api/v1/jobs', {
      auth: true,
      query: { page: 1, pageSize: 20, scope: 'persona', scope_id: id },
    })
    const active = (data.list ?? []).find(
      (job) => job.template_type === 'style-8d' && !isTerminalJobStatus(job.status),
    )
    if (!active) {
      setStyleJob(null)
      setStyleJobId(null)
      return
    }
    setStyleJob(active)
    setStyleJobId(active.id)
  }, [id])

  useEffect(() => {
    if (!id) return
    setLoading(true)
    setError('')
    Promise.all([loadPersona(), loadActiveStyleJob()])
      .catch((e) => setError(e instanceof ApiError ? e.message : '載入人設失敗'))
      .finally(() => setLoading(false))
  }, [id, loadPersona, loadActiveStyleJob])

  useEffect(() => {
    if (!styleJobId) return
    const timer = window.setInterval(() => {
      refreshStyleJob(styleJobId).catch(() => undefined)
    }, 3000)
    return () => window.clearInterval(timer)
  }, [styleJobId, refreshStyleJob])

  const visibleStyle =
    styleResult ?? createEmptyStyle8DProfile(benchmarkUsername.replace(/^@/, '').trim())

  const completeness = useMemo(
    () => profileCompleteness(draft, !!styleResult),
    [draft, styleResult],
  )

  const save = async () => {
    if (!id) return
    setBusy('save')
    setError('')
    setMessage('')
    try {
      const data = await api.patch<PersonaData>(
        `/api/v1/personas/${encodeURIComponent(id)}`,
        {
          display_name: draft.display_name,
          persona: draft.persona,
          brief: draft.brief,
          style_profile: draft.style_profile,
          style_benchmark: benchmarkUsername.replace(/^@/, '').trim(),
        },
        { auth: true },
      )
      setDraft({ ...emptyPersona(), ...data })
      setStyleResult(parseStyle8DProfile(data.style_profile))
      setBenchmarkUsername(data.style_benchmark ?? '')
      setMessage('人設已儲存')
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '儲存失敗')
    } finally {
      setBusy(null)
    }
  }

  const analyzeBenchmark = async () => {
    if (!id || !benchmarkUsername.trim()) return
    setBusy('8d')
    setError('')
    setMessage('')
    try {
      const data = await api.post<{ job_id: string; message?: string }>(
        `/api/v1/personas/${encodeURIComponent(id)}/style-analysis`,
        { benchmark_username: benchmarkUsername.trim() },
        { auth: true },
      )
      setMessage(data.message ?? '8D 分析已在背景執行，可自由切換頁面')
      setStyleJobId(data.job_id)
      await refreshStyleJob(data.job_id)
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '8D 分析失敗')
    } finally {
      setBusy(null)
    }
  }

  const updateStyleDimension = (key: Style8DKey, summary: string) => {
    const base = styleResult ?? createEmptyStyle8DProfile(benchmarkUsername.replace(/^@/, '').trim())
    const next: StoredStyle8DProfile = {
      ...base,
      analysis: {
        ...base.analysis,
        [key]: { ...base.analysis[key], summary },
      },
    }
    setStyleResult(next)
    setDraft((prev) => ({ ...prev, style_profile: JSON.stringify(next) }))
  }

  const syncPersonaFrom8D = () => {
    if (!styleResult?.personaDraft) return
    setDraft((prev) => ({ ...prev, persona: styleResult.personaDraft }))
  }

  const remove = async () => {
    if (!id) return
    const label = draft.display_name?.trim() || '未命名人設'
    if (!window.confirm(`確定要刪除「${label}」？刪除後無法復原。`)) return
    setBusy('delete')
    setError('')
    setMessage('')
    try {
      await api.delete(`/api/v1/personas/${encodeURIComponent(id)}`, { auth: true })
      navigate('/personas')
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '刪除失敗')
    } finally {
      setBusy(null)
    }
  }

  if (!id) {
    return (
      <Card>
        <p className="text-sm text-muted">未指定人設。</p>
      </Card>
    )
  }

  return (
    <div className="ac-persona-page">
      <AcLink to="/personas" className="inline-flex items-center gap-1.5 text-sm">
        ← 返回人設庫
      </AcLink>

      {/* 島民護照 Hero */}
      <header className="ac-persona-passport">
        <PassportIslandArt className="ac-persona-passport-scene" />
        <LeafSparkleArt className="ac-persona-passport__leaf" />

        <div className="relative z-[1] flex flex-col gap-6 lg:flex-row lg:items-end lg:justify-between">
          <div className="min-w-0 flex-1 space-y-4">
            <div className="flex flex-wrap items-center gap-3">
              <span className="ac-persona-passport__label display-en">Island Resident</span>
              <AcIcon app="persona" size="lg" />
            </div>

            <div>
              <p className="text-sm font-bold text-muted">島民檔案名稱</p>
              <Input
                value={draft.display_name ?? ''}
                onChange={(e) => setDraft((prev) => ({ ...prev, display_name: e.target.value }))}
                placeholder="給自己看的名稱"
                disabled={loading}
                className="mt-2 !border-wood/60 !bg-surface/90 !py-3.5 !text-xl !font-bold"
              />
            </div>

            <p className="max-w-xl text-sm leading-relaxed text-ink-secondary">
              這份人設只定義回覆與發文的語氣策略，可套用到多個 Threads 帳號。產品與受眾定位請到品牌庫設定。
            </p>

            <div className="flex flex-wrap items-center gap-2">
              {styleResult ? <Badge tone="success">8D 已建立</Badge> : <Badge tone="sky">8D 待分析</Badge>}
              {benchmarkUsername.trim() ? (
                <span className="text-xs font-semibold text-muted">
                  對標 @{benchmarkUsername.replace(/^@/, '')}
                </span>
              ) : null}
            </div>

            <div className="ac-persona-mile-bar">
              <div className="flex items-center justify-between gap-2">
                <span className="ac-persona-mile-bar__label">檔案完成度</span>
                <span className="text-xs font-black text-brand">{completeness}%</span>
              </div>
              <ProgressBar value={completeness} />
            </div>
          </div>

          <div className="flex shrink-0 flex-wrap gap-2 lg:flex-col lg:items-stretch">
            <Button onClick={save} disabled={busy === 'save' || loading || busy === 'delete'}>
              {busy === 'save' ? '儲存中…' : '儲存人設'}
            </Button>
            <Button
              variant="danger"
              onClick={() => void remove()}
              disabled={loading || busy === 'delete' || busy === 'save'}
            >
              {busy === 'delete' ? '刪除中…' : '刪除人設'}
            </Button>
          </div>
        </div>
      </header>

      <div className="grid gap-10 xl:grid-cols-[minmax(0,1fr)_minmax(0,1.15fr)] xl:gap-12">
        {/* 左欄：身份檔案 */}
        <div className="space-y-10">
          <section>
            <ZoneSign>身份檔案</ZoneSign>
            <div className="ac-persona-zone">
              <div className="ac-persona-panel">
                <Field label="語氣定位（選填）">
                  <Textarea
                    rows={4}
                    value={draft.brief ?? ''}
                    onChange={(e) => setDraft((prev) => ({ ...prev, brief: e.target.value }))}
                    placeholder="這個語氣怎麼說話、用什麼觀點（非產品定位）"
                    data-islander-label="一句話定位"
                    disabled={loading}
                  />
                </Field>
              </div>

              <div className="ac-persona-field-card">
                <Field label="人設與語氣">
                  <Textarea
                    rows={6}
                    value={draft.persona ?? ''}
                    onChange={(e) => setDraft((prev) => ({ ...prev, persona: e.target.value }))}
                    placeholder="像誰、怎麼說話、常用語氣、哪些話不要說"
                    data-islander-label="人設與語氣"
                    disabled={loading}
                  />
                </Field>
              </div>
            </div>
          </section>

        </div>

        {/* 右欄：8D 風格雷達 */}
        <section id="style-8d">
          <ZoneSign>8D 風格雷達</ZoneSign>
          <div className="ac-persona-zone">
            <div className="ac-persona-research">
              <ResearchHutArt className="ac-persona-research__art" />
              <div className="relative z-[1] max-w-[calc(100%-4rem)] space-y-4">
                <div>
                  <p className="text-sm font-bold text-ink">對標帳號研究台</p>
                  <p className="mt-1 text-sm leading-relaxed text-ink-secondary">
                    分析後會存成這份人設的風格策略，產文與回覆都會自動套用。
                  </p>
                </div>
                <div className="flex flex-col gap-3 sm:flex-row sm:items-center">
                  <Input
                    value={benchmarkUsername}
                    onChange={(e) => setBenchmarkUsername(e.target.value)}
                    placeholder="@對標帳號"
                    disabled={loading || !!styleJob}
                    className="flex-1"
                  />
                  <Button
                    onClick={analyzeBenchmark}
                    disabled={busy === '8d' || !!styleJob || !benchmarkUsername.trim() || loading}
                    className="sm:shrink-0"
                  >
                    {styleJob ? '8D 任務進行中' : busy === '8d' ? '建立任務中…' : '開始 8D 分析'}
                  </Button>
                </div>
              </div>
            </div>

            {styleJob ? (
              <div className="ac-island-card p-5">
                <p className="mb-3 text-xs font-bold text-brand">可自由切換頁面，任務不會中斷</p>
                <Style8DJobPanel job={styleJob} />
                {styleJob.status === 'queued' || styleJob.status === 'waiting_worker' ? (
                  <div className="mt-4">
                    <Notice
                      tone="warning"
                      title="任務尚未被 Worker 接手"
                      message="請確認已另開終端執行 make node-worker-style-8d（或 npm run worker:style-8d），且 API 服務在 :8890 運行。"
                    />
                  </div>
                ) : null}
              </div>
            ) : null}

            {!styleResult && !styleJob ? (
              <Notice
                tone="info"
                title="尚未建立 8D 風格策略"
                message="八個維度列在下方。你可以先手動填寫，或輸入對標帳號交給 AI 分析。"
              />
            ) : null}

            {styleResult ? <Style8DAnalysisMeta profile={styleResult} /> : null}

            <Style8DDimensionEditor
              analysis={visibleStyle.analysis}
              samplePosts={visibleStyle.samplePosts}
              loading={loading}
              onUpdate={updateStyleDimension}
            />

            {styleResult ? (
              <div className="ac-persona-panel flex flex-wrap items-center gap-3">
                <Button variant="soft" onClick={syncPersonaFrom8D}>
                  同步成左欄人設文字
                </Button>
                <p className="text-xs leading-relaxed text-muted">
                  8D 已會自動生效；這顆按鈕只在你想把摘要同步到人設文字時使用。
                </p>
              </div>
            ) : null}
          </div>
        </section>
      </div>

      <ErrorText message={error} />
      <SuccessText message={message} />
    </div>
  )
}