"use client";

import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import {
  ArrowLeft,
  Loader2,
  MessageSquare,
  Radar,
  RefreshCw,
  Save,
  Sparkles,
  Table2,
} from "lucide-react";
import { ResearchMapView } from "@/components/research-map-view";
import { SuggestedTagsPicker } from "@/components/suggested-tags-picker";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { FeatureGate } from "@/components/layout/feature-gate";
import { PageHeader } from "@/components/layout/page-header";
import { JobProgressPanel } from "@/components/job-progress-panel";
import { openRefine, registerApplyCallback, syncResearchMap } from "@/lib/refine-session/store";
import { reconcileSelectedTags } from "@/lib/services/preserve-selected-tags";
import { Textarea } from "@/components/ui/textarea";
import { InlineAlert } from "@/components/ui/inline-alert";
import { notify } from "@/lib/notifications/store";
import type { ActionFeedback } from "@/lib/use-action-feedback";
import { useActionFeedback } from "@/lib/use-action-feedback";
import type { ResearchMap } from "@/lib/types/research";
import { BrandProductPicker } from "@/components/product-profile/brand-product-picker";
import { hasProductContext, summarizeProductContext } from "@/lib/types/product-context";
import { TOPIC_GOAL_LABELS, isPlacementGoal } from "@/lib/types/topic-goal";
import { parseFetchJson } from "@/lib/utils";
import { parseStyle8DProfile } from "@/lib/types/style-profile";

interface Topic {
  id: string;
  label: string;
  query: string;
  brief: string | null;
  productContext: string | null;
  brandProfileId?: string | null;
  productProfileId?: string | null;
  topicGoal: string;
  researchMap: string | null;
  selectedTags: string | null;
  active: boolean;
}

function parseResearchMap(raw: string | null): ResearchMap | null {
  if (!raw) return null;
  try {
    return JSON.parse(raw) as ResearchMap;
  } catch {
    return null;
  }
}

function parseTags(raw: string | null): string[] {
  if (!raw) return [];
  try {
    const parsed = JSON.parse(raw) as unknown;
    return Array.isArray(parsed) ? parsed.filter((t): t is string => typeof t === "string") : [];
  } catch {
    return [];
  }
}

export default function TopicDetailPage() {
  const params = useParams();
  const router = useRouter();
  const topicId = params.topicId as string;

  const [topic, setTopic] = useState<Topic | null>(null);
  const [brief, setBrief] = useState("");
  const [productContext, setProductContext] = useState("");
  const [brandProfileId, setBrandProfileId] = useState<string | null>(null);
  const [productProfileId, setProductProfileId] = useState<string | null>(null);
  const [researchMap, setResearchMap] = useState<ResearchMap | null>(null);
  const [selectedTags, setSelectedTags] = useState<string[]>([]);
  const [analyzing, setAnalyzing] = useState(false);
  const [analyzeElapsed, setAnalyzeElapsed] = useState(0);
  const [analyzeError, setAnalyzeError] = useState<string | null>(null);
  const [analyzeProgress, setAnalyzeProgress] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [analyzingTags, setAnalyzingTags] = useState(false);
  const [scanning, setScanning] = useState(false);
  const [scanProgress, setScanProgress] = useState<string | null>(null);
  const [scanProgressDetail, setScanProgressDetail] = useState<string | null>(null);
  const [showScanSummary, setShowScanSummary] = useState(false);
  const [activeScanJobId, setActiveScanJobId] = useState<string | null>(null);
  const [cancellingScan, setCancellingScan] = useState(false);
  const [generating, setGenerating] = useState(false);
  const [lastScanId, setLastScanId] = useState<string | null>(null);
  const [style8DReady, setStyle8DReady] = useState(false);
  const { feedback, clearFeedback, showError, showSuccess, showWarning } =
    useActionFeedback();
  const [brandFeedback, setBrandFeedback] = useState<ActionFeedback | null>(null);
  const [tagsFeedback, setTagsFeedback] = useState<ActionFeedback | null>(null);
  const [scanFeedback, setScanFeedback] = useState<ActionFeedback | null>(null);
  const load = useCallback(async () => {
    const [topicsRes, scansRes, accountsRes] = await Promise.all([
      fetch("/api/topics"),
      fetch("/api/scans"),
      fetch("/api/accounts"),
    ]);
    const topicsData = await topicsRes.json();
    const scansData = await scansRes.json();
    const accountsData = (await accountsRes.json()) as {
      activeAccountId?: string | null;
      accounts?: Array<{ id: string; styleProfile?: string | null }>;
    };
    const activeAccount = accountsData.accounts?.find(
      (row) => row.id === accountsData.activeAccountId
    ) ?? accountsData.accounts?.[0];
    setStyle8DReady(!!parseStyle8DProfile(activeAccount?.styleProfile));
    const found = (topicsData.topics as Topic[]).find((t) => t.id === topicId);
    if (!found) return;
    setTopic(found);
    setBrief(found.brief ?? "");
    setProductContext(found.productContext ?? "");
    setBrandProfileId(found.brandProfileId ?? null);
    setProductProfileId(found.productProfileId ?? null);
    setResearchMap(parseResearchMap(found.researchMap));
    setSelectedTags(parseTags(found.selectedTags));

    const latestScan = (scansData.scans as Array<{ id: string; topicId: string }>).find(
      (s) => s.topicId === topicId
    );
    if (latestScan) setLastScanId(latestScan.id);
  }, [topicId]);

  const syncActiveJobs = useCallback(async () => {
    try {
      const res = await fetch(`/api/jobs?topicId=${topicId}&active=1`);
      const data = await parseFetchJson<{ jobs?: Array<{
        id: string;
        type: string;
        progress?: string | null;
        progressDetail?: string | null;
      }> }>(res);
      if (!res.ok) return;

      const active = data.jobs ?? [];
      const analyzeJob = active.find((j) => j.type === "analyze-topic");
      const scanJob = active.find((j) => j.type === "scan");

      setAnalyzing(!!analyzeJob);
      setAnalyzeProgress(analyzeJob?.progress ?? null);
      setScanning(!!scanJob);
      setScanProgress(scanJob?.progress ?? null);
      setScanProgressDetail(scanJob?.progressDetail ?? null);
      setActiveScanJobId(scanJob?.id ?? null);
    } catch {
      // 背景輪詢失敗時略過，避免整頁崩潰
    }
  }, [topicId]);

  useEffect(() => {
    if (!topic || !researchMap) return;
    syncResearchMap(topicId, researchMap, topic.label);
  }, [topicId, topic, researchMap]);

  useEffect(() => {
    return registerApplyCallback(topicId, (map) => {
      setSelectedTags((prev) => {
        const reconciled = reconcileSelectedTags(prev, map, {
          label: topic?.label ?? "",
          query: topic?.query ?? "",
          brief: topic?.brief,
        });
        setResearchMap(reconciled.researchMap);
        void fetch("/api/topics", {
          method: "PATCH",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            id: topicId,
            researchMap: reconciled.researchMap,
            selectedTags: reconciled.selectedTags,
          }),
        });
        return reconciled.selectedTags;
      });
    });
  }, [topicId, topic?.label, topic?.query, topic?.brief]);

  useEffect(() => {
    load();
    syncActiveJobs();
  }, [load, syncActiveJobs]);

  useEffect(() => {
    if (!analyzing && !scanning) return;
    const timer = window.setInterval(syncActiveJobs, 2000);
    return () => window.clearInterval(timer);
  }, [analyzing, scanning, syncActiveJobs]);

  useEffect(() => {
    if (!analyzing) {
      setAnalyzeElapsed(0);
      return;
    }
    const timer = window.setInterval(() => {
      setAnalyzeElapsed((s) => s + 1);
    }, 1000);
    return () => window.clearInterval(timer);
  }, [analyzing]);

  useEffect(() => {
    function onJobCompleted(event: Event) {
      const { job } = (event as CustomEvent).detail as {
        job: {
          topicId?: string | null;
          type: string;
          status: string;
          result?: string | null;
          error?: string | null;
          progress?: string | null;
          progressDetail?: string | null;
        };
      };
      if (job.topicId !== topicId) return;

      if (job.type === "analyze-topic") {
        setAnalyzing(false);
        setAnalyzeProgress(null);
        if (job.status === "completed") {
          setAnalyzeError(null);
          load();
        } else if (job.status === "failed") {
          setAnalyzeError(job.error ?? "AI 分析失敗");
        }
      }

      if (job.type === "scan") {
        setScanning(false);
        setActiveScanJobId(null);
        if (job.status === "completed") {
          setScanProgress(job.progress ?? "海巡完成");
          setScanProgressDetail(job.progressDetail ?? null);
          setShowScanSummary(true);
        } else {
          setScanProgress(null);
          setScanProgressDetail(null);
          setShowScanSummary(false);
          if (job.status === "failed") {
            setScanFeedback({
              type: "error",
              title: "海巡失敗",
              message: job.error ?? "海巡執行失敗，請再試一次。",
            });
          }
        }
        if (job.status === "completed" && job.result) {
          try {
            const scan = JSON.parse(job.result) as {
              id?: string;
              items?: Array<{ qualityTier?: string }>;
            };
            if (scan.id) {
              setLastScanId(scan.id);
              router.push(`/scans/${topicId}/results`);
            }
            load();
          } catch {
            load();
          }
        }
      }
    }

    window.addEventListener("job-completed", onJobCompleted);
    return () => window.removeEventListener("job-completed", onJobCompleted);
  }, [topicId, load, router]);

  async function handleSaveBrief() {
    if (!topic) return;
    clearFeedback();
    setSaving(true);
    const res = await fetch("/api/topics", {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ id: topic.id, brief }),
    });
    setSaving(false);
    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      showError((data as { error?: string }).error ?? "無法儲存 Brief", "儲存失敗");
      return;
    }
    showSuccess("Brief 已儲存");
    load();
  }

  async function handleAnalyze() {
    if (!topic) return;
    if (!brief.trim()) {
      showWarning("請先填寫主題 Brief，AI 才能準確分析。", "尚無 Brief");
      return;
    }
    if (
      isPlacementGoal(topic.topicGoal) &&
      !brandProfileId &&
      !hasProductContext(productContext)
    ) {
      showWarning("置入模式需要品牌與至少一項產品。", "請先選擇品牌");
      return;
    }

    setAnalyzeError(null);

    try {
      const res = await fetch("/api/analyze-topic", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ topicId: topic.id, brief }),
      });

      let data: { error?: string; jobId?: string; message?: string } = {};
      try {
        data = await res.json();
      } catch {
        throw new Error("伺服器回應格式錯誤");
      }

      if (!res.ok) {
        throw new Error(data.error ?? `AI 分析失敗（HTTP ${res.status}）`);
      }

      setAnalyzing(true);
      setAnalyzeProgress(data.message ?? "已於背景執行…");
      notify({
        type: "info",
        title: `${topic.label} · 主題分析中`,
        message: "AI 正在建立研究地圖與搜尋標籤，可以先去其他頁面。完成後會再通知你。",
        href: `/scans/${topic.id}`,
      });
      window.dispatchEvent(new Event("haixun:jobs-updated"));
      syncActiveJobs();
    } catch (err) {
      const message = err instanceof Error ? err.message : "AI 分析失敗";
      setAnalyzeError(message);
    }
  }

  function toggleTag(tag: string) {
    setSelectedTags((prev) =>
      prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]
    );
  }

  function selectAllAccountTags() {
    if (!researchMap) return;
    const accountTags = researchMap.suggestedTags
      .filter((t) => t.searchType === "帳號" || t.tag.startsWith("@"))
      .map((t) => t.tag);
    const fromSimilar = (researchMap.similarAccounts ?? []).map((a) =>
      a.username.startsWith("@") ? a.username : `@${a.username}`
    );
    setSelectedTags((prev) => [...new Set([...prev, ...accountTags, ...fromSimilar])]);
  }

  async function handleSaveTags() {
    if (!topic) return;
    setSaving(true);
    await fetch("/api/topics", {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ id: topic.id, selectedTags }),
    });
    setSaving(false);
    setTagsFeedback({ type: "success", message: "標籤已儲存" });
    load();
  }

  async function handleAnalyzeTags() {
    if (!topic || !researchMap || analyzingTags) return;
    setTagsFeedback(null);
    setAnalyzingTags(true);
    try {
      const res = await fetch("/api/analyze-tags", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ topicId: topic.id }),
      });
      const data = await parseFetchJson<{
        error?: string;
        researchMap?: ResearchMap;
        selectedTags?: string[];
        count?: number;
      }>(res);
      if (!res.ok || !data.researchMap || !data.selectedTags) {
        throw new Error(data.error ?? "搜尋標籤分析沒有回傳可用結果");
      }
      setResearchMap(data.researchMap);
      setSelectedTags(data.selectedTags);
      setTagsFeedback({
        type: "success",
        message: `已重新產生 ${data.count ?? data.selectedTags.length} 個自然搜尋詞，研究地圖未重新分析。`,
      });
    } catch (error) {
      setTagsFeedback({
        type: "error",
        title: "標籤分析失敗",
        message: error instanceof Error ? error.message : "請重試或更換研究模型",
      });
    } finally {
      setAnalyzingTags(false);
    }
  }

  async function handleScan() {
    if (!topic) return;
    setScanFeedback(null);
    setShowScanSummary(false);
    const placement = isPlacementGoal(topic.topicGoal);
    if (!placement && selectedTags.length === 0) {
      setScanFeedback({
        type: "warning",
        title: "請先選擇標籤",
        message: "完成 AI 分析後，至少選擇一個搜尋標籤再海巡。",
      });
      return;
    }
    if (
      placement &&
      (!researchMap ||
        (researchMap.questions.length === 0 && researchMap.pillars.length === 0))
    ) {
      setScanFeedback({
        type: "warning",
        title: "請先完成 AI 分析",
        message: "置入模式需要研究地圖的「受眾會問什麼」與「內容支柱」才能自動海巡。",
      });
      return;
    }
    setScanning(true);
    try {
      const res = await fetch("/api/scan", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          topicId: topic.id,
          useTags: !placement,
          selectedTags,
        }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error ?? "無法啟動海巡");
      setActiveScanJobId(data.jobId ?? null);
      setScanProgress(data.message ?? "海巡已啟動…");
      notify({
        type: "info",
        title: `${topic.label} · 海巡中`,
        message: "正在搜尋 Threads 並篩選素材，完成後會再通知你。",
        href: `/scans/${topic.id}`,
      });
      window.dispatchEvent(new Event("haixun:jobs-updated"));
      syncActiveJobs();
    } catch (error) {
      setScanning(false);
      setScanFeedback({
        type: "error",
        title: "海巡失敗",
        message: error instanceof Error ? error.message : "無法啟動海巡",
      });
    }
  }

  async function handleCancelScan() {
    if (!activeScanJobId) return;
    setCancellingScan(true);
    try {
      const res = await fetch(`/api/jobs/${activeScanJobId}/cancel`, { method: "POST" });
      const data = await res.json();
      if (!res.ok) {
        setScanFeedback({
          type: "error",
          title: "取消失敗",
          message: data.error ?? "無法停止海巡",
        });
        return;
      }
      setScanning(false);
      setScanProgress(null);
      setScanProgressDetail(null);
      setActiveScanJobId(null);
      setScanFeedback({ type: "info", message: "海巡已停止" });
      syncActiveJobs();
    } finally {
      setCancellingScan(false);
    }
  }

  async function handleGenerateMatrix() {
    if (!lastScanId) {
      setScanFeedback({ type: "warning", message: "請先完成海巡再生成內容矩陣。" });
      return;
    }
    setGenerating(true);
    const res = await fetch("/api/generate-matrix", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ scanId: lastScanId }),
    });
    const data = await res.json();
    setGenerating(false);
    if (!res.ok) {
      notify({ type: "error", title: "生成內容矩陣失敗", message: data.error });
      return;
    }
    notify({
      type: "success",
      title: "內容矩陣已生成",
      message: `共 ${data.drafts?.length ?? 0} 篇`,
      href: "/matrix",
    });
    router.push("/matrix");
  }

  if (!topic) {
    return (
      <div className="flex items-center justify-center py-20">
        <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
      </div>
    );
  }

  return (
    <div>
      <div className="mb-4">
        <Button variant="ghost" size="sm" asChild>
          <Link
            href={`/scans?mode=${isPlacementGoal(topic.topicGoal) ? "placement" : "viral"}`}
          >
            <ArrowLeft className="h-4 w-4" />
            返回主題列表
          </Link>
        </Button>
      </div>

      <PageHeader
        title={topic.label}
        description={`${topic.query} · ${TOPIC_GOAL_LABELS[isPlacementGoal(topic.topicGoal) ? "placement" : "viral"]}`}
      />

      <div className="mb-5 flex flex-col gap-3 rounded-xl border border-border bg-card p-4 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <div className="flex items-center gap-2">
            <p className="text-sm font-medium">帳號 8D 風格策略</p>
            <Badge variant={style8DReady ? "success" : "secondary"}>
              {style8DReady ? "已套用" : "尚未設定"}
            </Badge>
          </div>
          <p className="mt-1 text-xs text-muted-foreground">
            這份策略會自動影響後續產文與回覆；D1–D8 欄位在帳號策略頁編輯。
          </p>
        </div>
        <Button asChild variant="outline" size="sm">
          <Link href="/accounts#style-8d">查看 D1–D8</Link>
        </Button>
      </div>

      {feedback && (
        <InlineAlert
          type={feedback.type}
          title={feedback.title}
          message={feedback.message}
          onDismiss={clearFeedback}
          className="mb-4"
        />
      )}

      <div className="space-y-5">
        <Card>
          <CardHeader>
            <CardTitle>① 主題 Brief</CardTitle>

          </CardHeader>
          <CardContent className="space-y-3">
            <Textarea
              value={brief}
              onChange={(e) => setBrief(e.target.value)}
              rows={5}
              placeholder={
                isPlacementGoal(topic.topicGoal)
                  ? "例：服務自己在家幫狗洗澡的飼主，不要送寵物美容的受眾。"
                  : "例：30 歲上班族女性第一次備孕。想分享科學備孕知識，服務同齡焦慮型讀者。不要業配、偏方、純情緒宣洩。"
              }
            />
            {isPlacementGoal(topic.topicGoal) && (
              <div className="space-y-2 rounded-lg border border-border bg-muted/40 p-4">
                {brandFeedback && (
                  <InlineAlert
                    type={brandFeedback.type}
                    title={brandFeedback.title}
                    message={brandFeedback.message}
                    onDismiss={() => setBrandFeedback(null)}
                  />
                )}
                <BrandProductPicker
                  brandId={brandProfileId}
                  productId={productProfileId}
                  onChange={async ({ brandId, productId, context }) => {
                    setBrandFeedback(null);
                    const res = await fetch("/api/topics", {
                      method: "PATCH",
                      headers: { "Content-Type": "application/json" },
                      body: JSON.stringify({
                        id: topic.id,
                        brandProfileId: brandId,
                        productProfileId: productId,
                      }),
                    });
                    let data: { error?: string; topic?: { productContext?: string } } = {};
                    try {
                      data = await parseFetchJson(res);
                    } catch (err) {
                      setBrandFeedback({
                        type: "error",
                        title: "儲存失敗",
                        message: err instanceof Error ? err.message : "伺服器回應異常",
                      });
                      return;
                    }
                    if (!res.ok) {
                      setBrandFeedback({
                        type: "error",
                        title: "儲存失敗",
                        message: data.error ?? "無法連結品牌與產品",
                      });
                      return;
                    }
                    setBrandProfileId(brandId);
                    setProductProfileId(productId);
                    if (data.topic?.productContext) {
                      setProductContext(data.topic.productContext);
                    } else if (context) {
                      setProductContext(context);
                    }
                    setBrandFeedback({ type: "success", message: "品牌與產品已連結" });
                  }}
                />
                {!brandProfileId && !productProfileId && summarizeProductContext(productContext) && (
                  <p className="text-[12px] text-muted-foreground">
                    目前使用舊版內嵌資料：{summarizeProductContext(productContext)}
                  </p>
                )}
              </div>
            )}
            <Button size="sm" onClick={handleSaveBrief} disabled={saving}>
              <Save className="h-3.5 w-3.5" />
              {saving ? "儲存中…" : "儲存"}
            </Button>
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <div className="flex items-start justify-between gap-4">
              <div>
                <CardTitle>② 研究地圖</CardTitle>

              </div>
              <div className="flex shrink-0 flex-wrap gap-2">
                {researchMap && (
                  <FeatureGate feature="research">
                    <Button
                      variant="outline"
                      onClick={() =>
                        openRefine(topicId, { researchMap, topicLabel: topic.label })
                      }
                    >
                      <MessageSquare className="h-4 w-4" />
                      微調
                    </Button>
                  </FeatureGate>
                )}
                <FeatureGate feature="analyze">
                  <Button onClick={handleAnalyze} disabled={analyzing}>
                    {analyzing ? (
                      <Loader2 className="h-4 w-4 animate-spin" />
                    ) : (
                      <Sparkles className="h-4 w-4" />
                    )}
                    {analyzing ? `主題分析中… ${analyzeElapsed}s` : "主題分析"}
                  </Button>
                </FeatureGate>
              </div>
            </div>
          </CardHeader>
          <CardContent>
            {analyzing && (
              <p className="page-lead mb-3">
                {analyzeProgress ?? "分析中…"}
                {analyzeElapsed > 0 && ` · ${analyzeElapsed}s`}
              </p>
            )}
            {analyzeError && !analyzing && (
              <InlineAlert type="error" title="AI 分析失敗" message={analyzeError} className="mb-3" />
            )}
            <FeatureGate feature="analyze" showHint />
            {researchMap ? (
              <ResearchMapView
                map={researchMap}
                showSimilarAccounts={!isPlacementGoal(topic.topicGoal)}
              />
            ) : (
              <p className="page-lead">填好 Brief 後按「分析」</p>
            )}
          </CardContent>
        </Card>

        {researchMap && (
          <Card>
            <CardHeader>
              <div className="flex items-start justify-between gap-4">
                <div>
                  <CardTitle>③ {isPlacementGoal(topic.topicGoal) ? "海巡關鍵字" : "搜尋標籤"}</CardTitle>
                  <CardDescription className="mt-1">
                    {isPlacementGoal(topic.topicGoal)
                      ? "以真人會搜尋的痛點、求助與選購詞找出高意向受眾"
                      : "勾選後以 Threads API 與網搜找參考貼文；可一併勾選相似帳號"}
                  </CardDescription>
                </div>
                <div className="flex shrink-0 flex-wrap gap-2">
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={handleAnalyzeTags}
                    disabled={analyzingTags}
                  >
                    {analyzingTags ? (
                      <Loader2 className="h-3.5 w-3.5 animate-spin" />
                    ) : (
                      <RefreshCw className="h-3.5 w-3.5" />
                    )}
                    {analyzingTags ? "分析標籤中…" : "重新分析標籤"}
                  </Button>
                  <Button size="sm" variant="outline" onClick={handleSaveTags} disabled={saving || analyzingTags}>
                    儲存標籤
                  </Button>
                </div>
              </div>
            </CardHeader>
            <CardContent className="space-y-3">
              {tagsFeedback && (
                <InlineAlert
                  type={tagsFeedback.type}
                  title={tagsFeedback.title}
                  message={tagsFeedback.message}
                  onDismiss={() => setTagsFeedback(null)}
                />
              )}
              <SuggestedTagsPicker
                tags={researchMap.suggestedTags}
                selected={selectedTags}
                onToggle={toggleTag}
                onSelectAllAccounts={selectAllAccountTags}
                hideAccounts={isPlacementGoal(topic.topicGoal)}
                researchMap={researchMap}
              />
            </CardContent>
          </Card>
        )}

        <Card>
          <CardHeader>
            <CardTitle>④ 海巡與產出</CardTitle>
            <CardDescription>
              {isPlacementGoal(topic.topicGoal)
                ? "分析完成後一鍵海巡：自動用受眾問題與內容支柱搜尋，再以「不要碰」過濾"
                : "海巡後生成內容矩陣"}
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-3">
            {scanFeedback && (
              <InlineAlert
                type={scanFeedback.type}
                title={scanFeedback.title}
                message={scanFeedback.message}
                onDismiss={() => setScanFeedback(null)}
              />
            )}
            {(scanning || showScanSummary) && (scanProgress || scanProgressDetail) && (
              <div className="space-y-2 rounded-lg border border-border bg-muted/50 p-3">
                <JobProgressPanel
                  summary={scanProgress ?? (scanning ? "背景海巡中…" : "海巡完成")}
                  progressDetailRaw={scanProgressDetail}
                  completed={!scanning && showScanSummary}
                  jobType="scan"
                />
                {scanning ? (
                  <p className="page-lead">可換頁 · 取消於下個子任務後生效</p>
                ) : (
                  <div className="flex flex-wrap items-center gap-2">
                    <p className="page-lead">海巡與留言抓取已完成，請自行挑選貼文</p>
                    <Button
                      size="sm"
                      variant="ghost"
                      className="h-7 px-2 text-[12px]"
                      onClick={() => {
                        setShowScanSummary(false);
                        setScanProgress(null);
                        setScanProgressDetail(null);
                      }}
                    >
                      關閉
                    </Button>
                  </div>
                )}
              </div>
            )}
            <FeatureGate feature="scan" showHint className="mb-3" />
            <div className="flex flex-wrap gap-2">
            <FeatureGate feature="scan">
            <Button
              onClick={handleScan}
              disabled={
                scanning ||
                (!isPlacementGoal(topic.topicGoal) && selectedTags.length === 0) ||
                (isPlacementGoal(topic.topicGoal) && !researchMap)
              }
            >
              <Radar className="h-4 w-4" />
              {scanning
                ? "海巡中…"
                : isPlacementGoal(topic.topicGoal)
                  ? "置入海巡"
                  : `綜合海巡（${selectedTags.length} 個標籤）`}
            </Button>
            </FeatureGate>
            {scanning && activeScanJobId && (
              <Button
                variant="outline"
                onClick={handleCancelScan}
                disabled={cancellingScan}
              >
                {cancellingScan ? (
                  <Loader2 className="h-4 w-4 animate-spin" />
                ) : null}
                停止海巡
              </Button>
            )}
            {!isPlacementGoal(topic.topicGoal) && (
              <Button
                variant="outline"
                onClick={handleGenerateMatrix}
                disabled={generating || !lastScanId}
              >
                <Table2 className="h-4 w-4" />
                {generating ? "生成中…" : "生成內容矩陣"}
              </Button>
            )}
            <Button variant="ghost" asChild>
              <Link href={`/scans/${topicId}/results`}>
                查看海巡成果
              </Link>
            </Button>
            </div>
          </CardContent>
        </Card>
      </div>

    </div>
  );
}
