import { useCallback, useEffect, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import { api, ApiError } from '../api/client'
import { PlacementFlowNav } from '../components/PlacementFlowNav'
import { ReplyPersonaPicker } from '../components/ReplyPersonaPicker'
import { useActiveBrand } from '../hooks/useActiveBrand'
import { getReplyPersonaId } from '../lib/brandContext'
import {
  Badge,
  Button,
  Card,
  ErrorText,
  Field,
  Notice,
  Select,
  Textarea,
} from '../components/ui'
import { useIslanderPage } from '../lib/islander'
import {
  OUTREACH_DRAFT_EVENT,
  OUTREACH_DRAFT_LABEL,
  bindOutreachIslanderActions,
  ensureOutreachActionHandlers,
  generateOutreachDraftRemote,
  unbindOutreachIslanderActions,
  type OutreachDraftData,
} from '../lib/islander/outreachActions'


export type ScanPostData = {
  id: string
  graph_node_id: string
  search_tag: string
  query_dimension: string
  external_id: string
  permalink: string
  author: string
  text: string
  priority: string
  placement_score: number
  product_fit_score: number
  solved_by_product: boolean
  source: string
  scan_job_id: string
  outreach_status?: string
  published_reply_id?: string
  published_permalink?: string
  outreach_update_at?: number
  replies?: Array<{
    external_id?: string
    author?: string
    text: string
    permalink?: string
    like_count?: number
    posted_at?: string
  }>
  create_at: number
}

const PRIORITY_LABEL: Record<string, string> = {
  gold: '雙軌命中',
  recent: '近期軌',
  relevant: '相關軌',
}

const OUTREACH_STATUS_LABEL: Record<string, string> = {
  pending: '待處理',
  drafted: '已草稿',
  published: '已發送',
  handled: '已處理',
  skipped: '已略過',
}

function outreachTone(status: string): 'success' | 'warning' | 'sky' | 'neutral' {
  if (status === 'published' || status === 'handled') return 'success'
  if (status === 'drafted') return 'sky'
  if (status === 'skipped') return 'warning'
  return 'neutral'
}

function priorityTone(priority: string): 'success' | 'warning' | 'sky' | 'neutral' {
  if (priority === 'gold') return 'success'
  if (priority === 'recent') return 'warning'
  if (priority === 'relevant') return 'sky'
  return 'neutral'
}

ensureOutreachActionHandlers()

export function PersonaOutreachPage() {
  const { brandId: id, brand, brands, setBrandId, loading: brandLoading } = useActiveBrand()
  const [replyPersonaId, setReplyPersonaId] = useState(getReplyPersonaId)

  const [posts, setPosts] = useState<ScanPostData[]>([])
  const [draftsByPost, setDraftsByPost] = useState<Record<string, OutreachDraftData>>({})
  const [selectedDraftIndex, setSelectedDraftIndex] = useState<Record<string, number>>({})
  const [draftTextByPost, setDraftTextByPost] = useState<Record<string, string>>({})
  const [generatingPostId, setGeneratingPostId] = useState<string | null>(null)
  const [publishingPostId, setPublishingPostId] = useState<string | null>(null)
  const [patchingPostId, setPatchingPostId] = useState<string | null>(null)
  const [priority, setPriority] = useState('')
  const [recent7d, setRecent7d] = useState(true)
  const [productFitMin, setProductFitMin] = useState(70)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')

  useIslanderPage({
    title: '獲客台',
    purpose: '檢視海巡貼文、評估 productFitScore、產生獲客留言草稿',
    hints: [
      'gold = 相關軌與近期軌都命中',
      '預設篩 7 天內（gold/recent）與產品可解',
      '可用島民 generateOutreachReply 產生草稿並填入「獲客留言草稿」',
      'Threads API 連線後可用 publishOutreach 發送（需 confirm=true）',
      '手動處理完可標記 handled 或 skipped',
    ],
    suggestions: ['哪幾篇適合留言？', '幫我寫獲客留言', '幫我發送這則留言'],
  })

  const generateForPost = useCallback(
    async (scanPostId: string, count = 2) => {
      if (!id) return null
      setGeneratingPostId(scanPostId)
      setError('')
      try {
        const data = await generateOutreachDraftRemote(id, scanPostId, count, replyPersonaId)
        setDraftsByPost((prev) => ({ ...prev, [scanPostId]: data }))
        setSelectedDraftIndex((prev) => ({ ...prev, [scanPostId]: 0 }))
        const primary = data.drafts[0]?.text ?? ''
        setDraftTextByPost((prev) => ({ ...prev, [scanPostId]: primary }))
        return data
      } catch (e) {
        setError(e instanceof ApiError ? e.message : '產生獲客留言失敗')
        return null
      } finally {
        setGeneratingPostId(null)
      }
    },
    [id, replyPersonaId],
  )

  const publishForIslander = useCallback(
    async (scanPostId: string, text: string) => {
      if (!id) return null
      const result = await api.post<{ message: string; outreach_status: string; published_permalink?: string }>(
        `/api/v1/brands/${encodeURIComponent(id)}/outreach-drafts/publish`,
        { scan_post_id: scanPostId, text: text.trim(), confirm: true },
        { auth: true },
      )
      setPosts((prev) =>
        prev.map((p) =>
          p.id === scanPostId
            ? {
                ...p,
                outreach_status: result.outreach_status,
                published_permalink: result.published_permalink,
              }
            : p,
        ),
      )
      return result
    },
    [id],
  )

  const patchForIslander = useCallback(
    async (scanPostId: string, status: string) => {
      if (!id) return null
      const updated = await api.patch<ScanPostData>(
        `/api/v1/brands/${encodeURIComponent(id)}/scan-posts/${encodeURIComponent(scanPostId)}`,
        { outreach_status: status },
        { auth: true },
      )
      setPosts((prev) => prev.map((p) => (p.id === updated.id ? { ...p, ...updated } : p)))
      return updated
    },
    [id],
  )

  useEffect(() => {
    if (!id) return
    bindOutreachIslanderActions({
      brandId: id,
      generate: generateForPost,
      publish: publishForIslander,
      patchOutreach: patchForIslander,
    })
    return () => unbindOutreachIslanderActions()
  }, [id, generateForPost, publishForIslander, patchForIslander])

  useEffect(() => {
    const onDraft = (event: Event) => {
      const detail = (event as CustomEvent<{ scanPostId: string; draft: OutreachDraftData }>).detail
      if (!detail?.scanPostId || !detail.draft) return
      setDraftsByPost((prev) => ({ ...prev, [detail.scanPostId]: detail.draft }))
      setSelectedDraftIndex((prev) => ({ ...prev, [detail.scanPostId]: 0 }))
      const primary = detail.draft.drafts[0]?.text ?? ''
      setDraftTextByPost((prev) => ({ ...prev, [detail.scanPostId]: primary }))
    }
    window.addEventListener(OUTREACH_DRAFT_EVENT, onDraft)
    return () => window.removeEventListener(OUTREACH_DRAFT_EVENT, onDraft)
  }, [])

  const load = useCallback(async () => {
    if (!id) return
    setLoading(true)
    setError('')
    try {
      const postsData = await api.get<{ list: ScanPostData[]; total: number }>(
          `/api/v1/brands/${encodeURIComponent(id)}/scan-posts`,
          {
            auth: true,
            query: {
              priority: priority || undefined,
              recent_7d: recent7d,
              product_fit_min: productFitMin > 0 ? productFitMin : undefined,
              limit: 100,
            },
          },
        )
      setPosts(postsData.list ?? [])
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '載入獲客台失敗')
    } finally {
      setLoading(false)
    }
  }, [id, priority, recent7d, productFitMin])

  useEffect(() => {
    load().catch(() => undefined)
  }, [load])

  const stats = useMemo(() => {
    const gold = posts.filter((p) => p.priority === 'gold').length
    const solved = posts.filter((p) => p.solved_by_product).length
    return { gold, solved, total: posts.length }
  }, [posts])

  const updatePost = (updated: ScanPostData) => {
    setPosts((prev) => prev.map((p) => (p.id === updated.id ? { ...p, ...updated } : p)))
  }

  const patchOutreach = async (postId: string, outreachStatus: string) => {
    if (!id) return
    setPatchingPostId(postId)
    setError('')
    try {
      const updated = await api.patch<ScanPostData>(
        `/api/v1/brands/${encodeURIComponent(id)}/scan-posts/${encodeURIComponent(postId)}`,
        { outreach_status: outreachStatus },
        { auth: true },
      )
      updatePost(updated)
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '更新狀態失敗')
    } finally {
      setPatchingPostId(null)
    }
  }

  const publishDraft = async (postId: string, text: string) => {
    if (!id || !text.trim()) return
    const ok = window.confirm('確定透過 Threads API 發送這則獲客留言？')
    if (!ok) return
    setPublishingPostId(postId)
    setError('')
    try {
      const result = await api.post<{
        scan_post_id: string
        outreach_status: string
        published_permalink?: string
        message: string
      }>(
        `/api/v1/brands/${encodeURIComponent(id)}/outreach-drafts/publish`,
        { scan_post_id: postId, text: text.trim(), confirm: true },
        { auth: true },
      )
      setPosts((prev) =>
        prev.map((p) =>
          p.id === postId
            ? {
                ...p,
                outreach_status: result.outreach_status,
                published_permalink: result.published_permalink,
              }
            : p,
        ),
      )
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '發送留言失敗')
    } finally {
      setPublishingPostId(null)
    }
  }

  const selectDraft = (postId: string, index: number) => {
    const draft = draftsByPost[postId]
    if (!draft) return
    const text = draft.drafts[index]?.text ?? ''
    setSelectedDraftIndex((prev) => ({ ...prev, [postId]: index }))
    setDraftTextByPost((prev) => ({ ...prev, [postId]: text }))
  }

  if (!brandLoading && !id) {
    return (
      <div className="ac-persona-page space-y-8">
        <PlacementFlowNav
          active="outreach"
          brandId=""
          brands={brands}
          onBrandChange={setBrandId}
          brandLoading={brandLoading}
        />
        <Card>
          <p className="text-sm text-ink-secondary">
            請先在
            <Link to="/brands" className="mx-1 font-semibold text-brand hover:underline">
              品牌庫
            </Link>
            建立品牌，再進入找 TA。
          </p>
        </Card>
      </div>
    )
  }

  const brandName = brand?.display_name?.trim() || '未命名品牌'

  return (
    <div className="ac-persona-page space-y-8">
      <PlacementFlowNav
        active="outreach"
        brandId={id}
        brands={brands}
        onBrandChange={setBrandId}
        brandLoading={brandLoading}
      />

      <header className="space-y-2">
        <p className="display-en text-[10px] font-bold tracking-[0.16em] text-brand uppercase">
          Outreach
        </p>
        <h1 className="text-2xl font-black text-ink">找 TA · {brandName}</h1>
        <p className="max-w-2xl text-sm leading-relaxed text-ink-secondary">
          海巡結果依 productFitScore 與雙軌優先級排序。產生草稿後可透過 Threads API 發送，或手動貼文後標記處理狀態。
        </p>
        <div className="flex flex-wrap items-center gap-2">
          <Badge tone="sky">共 {stats.total} 篇</Badge>
          <Badge tone="success">gold {stats.gold}</Badge>
          <Badge tone="brand">產品可解 {stats.solved}</Badge>
        </div>
      </header>

      <section className="ac-persona-panel grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
        <ReplyPersonaPicker value={replyPersonaId} onChange={setReplyPersonaId} />
        <Field label="優先級">
          <Select value={priority} onChange={(e) => setPriority(e.target.value)}>
            <option value="">全部</option>
            <option value="gold">gold（雙軌命中）</option>
            <option value="recent">recent（近期軌）</option>
            <option value="relevant">relevant（相關軌）</option>
          </Select>
        </Field>
        <Field label="產品匹配下限">
          <Select
            value={String(productFitMin)}
            onChange={(e) => setProductFitMin(Number(e.target.value))}
          >
            <option value="0">不限</option>
            <option value="40">≥ 40</option>
            <option value="70">≥ 70（建議）</option>
            <option value="85">≥ 85</option>
          </Select>
        </Field>
        <Field label="近期窗口">
          <Select
            value={recent7d ? '7d' : 'all'}
            onChange={(e) => setRecent7d(e.target.value === '7d')}
          >
            <option value="7d">7 天內（gold/recent）</option>
            <option value="all">含 30 天補充</option>
          </Select>
        </Field>
      </section>

      {loading ? (
        <p className="text-sm text-ink-secondary">載入海巡結果…</p>
      ) : posts.length === 0 ? (
        <Notice
          tone="info"
          title="尚無海巡結果"
          message="請先到研究頁勾選節點並執行「雙軌海巡」。"
        />
      ) : (
        <div className="grid gap-4">
          {posts.map((post) => {
            const draft = draftsByPost[post.id]
            const draftIndex = selectedDraftIndex[post.id] ?? 0
            const draftText = draftTextByPost[post.id] ?? ''
            const busy = generatingPostId === post.id
            const publishing = publishingPostId === post.id
            const patching = patchingPostId === post.id
            const status = post.outreach_status || 'pending'
            const canPublish = status !== 'published' && status !== 'handled' && status !== 'skipped'

            return (
              <article
                key={post.id}
                className="ac-island-card space-y-3 p-5"
                data-islander-label={`獲客貼文 ${post.author}`}
                data-scan-post-id={post.id}
              >
                <div className="flex flex-wrap items-center gap-2">
                  <Badge tone={priorityTone(post.priority)}>
                    {PRIORITY_LABEL[post.priority] ?? post.priority}
                  </Badge>
                  <Badge tone={post.solved_by_product ? 'success' : 'warning'}>
                    產品匹配 {post.product_fit_score}
                  </Badge>
                  <Badge tone="neutral">{post.search_tag}</Badge>
                  <Badge tone={outreachTone(status)}>
                    {OUTREACH_STATUS_LABEL[status] ?? status}
                  </Badge>
                  <span className="text-xs text-muted">@{post.author}</span>
                </div>
                <p className="text-sm leading-relaxed text-ink">{post.text}</p>
                {post.replies?.length ? (
                  <details className="rounded-lg border border-line/50 bg-surface/40 p-3 text-sm">
                    <summary className="cursor-pointer font-semibold text-ink">
                      留言參考（{post.replies.length}）
                    </summary>
                    <ul className="mt-2 space-y-2">
                      {post.replies.slice(0, 5).map((reply, index) => (
                        <li key={`${post.id}-reply-${index}`} className="text-ink-secondary">
                          {reply.author ? <span className="font-medium text-ink">@{reply.author} </span> : null}
                          {reply.text}
                        </li>
                      ))}
                    </ul>
                  </details>
                ) : null}
                <div className="flex flex-wrap items-center gap-3 text-xs text-muted">
                  <span>置入分 {post.placement_score}</span>
                  <span>{post.query_dimension}</span>
                  <span>{post.source}</span>
                  <span className="font-mono text-[10px]">id:{post.id.slice(0, 8)}</span>
                  {post.permalink ? (
                    <a href={post.permalink} target="_blank" rel="noreferrer" className="ac-link">
                      開啟貼文
                    </a>
                  ) : null}
                  {post.published_permalink ? (
                    <a
                      href={post.published_permalink}
                      target="_blank"
                      rel="noreferrer"
                      className="ac-link"
                    >
                      已發留言
                    </a>
                  ) : null}
                </div>

                <div className="flex flex-wrap gap-2">
                  <Button
                    variant="soft"
                    disabled={busy || patching}
                    data-islander-label="產生獲客留言"
                    onClick={() => void generateForPost(post.id)}
                  >
                    {busy ? '產生中…' : '產生獲客留言'}
                  </Button>
                  {status !== 'handled' ? (
                    <Button
                      variant="ghost"
                      disabled={patching}
                      data-islander-label="標記已處理"
                      onClick={() => void patchOutreach(post.id, 'handled')}
                    >
                      {patching ? '更新中…' : '標記已處理'}
                    </Button>
                  ) : null}
                  {status !== 'skipped' ? (
                    <Button
                      variant="ghost"
                      disabled={patching}
                      onClick={() => void patchOutreach(post.id, 'skipped')}
                    >
                      略過
                    </Button>
                  ) : null}
                </div>

                {draft ? (
                  <div className="space-y-3 rounded-xl border border-line/60 bg-surface/50 p-4">
                    <div className="flex flex-wrap items-center gap-2 text-xs text-muted">
                      <span>相關度 {Math.round(draft.relevance * 100)}%</span>
                      {draft.reason ? <span>· {draft.reason}</span> : null}
                    </div>
                    {draft.drafts.length > 1 ? (
                      <div className="flex flex-wrap gap-2">
                        {draft.drafts.map((item, index) => (
                          <Button
                            key={`${post.id}-draft-${index}`}
                            variant={draftIndex === index ? 'primary' : 'ghost'}
                            className="text-xs"
                            onClick={() => selectDraft(post.id, index)}
                          >
                            切角 {index + 1}
                            {item.angle ? ` · ${item.angle}` : ''}
                          </Button>
                        ))}
                      </div>
                    ) : null}
                    {draft.drafts[draftIndex]?.rationale ? (
                      <p className="text-xs text-muted">{draft.drafts[draftIndex].rationale}</p>
                    ) : null}
                    <Field label={OUTREACH_DRAFT_LABEL} hint="島民可用 fill 或 applyDraft 填入此欄">
                      <Textarea
                        rows={5}
                        value={draftText}
                        data-islander-label={OUTREACH_DRAFT_LABEL}
                        onChange={(e) =>
                          setDraftTextByPost((prev) => ({ ...prev, [post.id]: e.target.value }))
                        }
                      />
                    </Field>
                    {canPublish && draftText.trim() ? (
                      <Button
                        variant="primary"
                        disabled={publishing}
                        data-islander-label="發送獲客留言"
                        onClick={() => void publishDraft(post.id, draftText)}
                      >
                        {publishing ? '發送中…' : '透過 Threads API 發送'}
                      </Button>
                    ) : null}
                  </div>
                ) : draftText.trim() && canPublish ? (
                  <div className="space-y-3 rounded-xl border border-line/60 bg-surface/50 p-4">
                    <Field label={OUTREACH_DRAFT_LABEL}>
                      <Textarea
                        rows={5}
                        value={draftText}
                        data-islander-label={OUTREACH_DRAFT_LABEL}
                        onChange={(e) =>
                          setDraftTextByPost((prev) => ({ ...prev, [post.id]: e.target.value }))
                        }
                      />
                    </Field>
                    <Button
                      variant="primary"
                      disabled={publishing}
                      onClick={() => void publishDraft(post.id, draftText)}
                    >
                      {publishing ? '發送中…' : '透過 Threads API 發送'}
                    </Button>
                  </div>
                ) : null}
              </article>
            )
          })}
        </div>
      )}

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