import { isOnTopicTag } from "@/lib/topic-anchor";
import { isPlacementGoal } from "@/lib/types/topic-goal";
import {
  isAccountTag,
  normalizeUsername,
  type ResearchMap,
} from "@/lib/types/research";

export type ScanTaskKind = "keyword" | "account";

export interface ScanTask {
  id: string;
  kind: ScanTaskKind;
  query: string;
  label: string;
  limit: number;
}

import { getBrowserConcurrency } from "@/lib/threads-browser/human-behavior";

const MAX_CONCURRENCY = 2;

export function splitScanTasks(tasks: ScanTask[]): {
  keywordTasks: ScanTask[];
  accountTasks: ScanTask[];
} {
  return {
    keywordTasks: tasks.filter((t) => t.kind === "keyword"),
    accountTasks: tasks.filter((t) => t.kind === "account"),
  };
}

/** 使用者明確勾選的 @帳號（不自動補研究地圖相似帳號）。 */
export function getSelectedAccountUsernames(selectedTags: string[]): string[] {
  return selectedTags
    .filter(isAccountTag)
    .map((tag) => normalizeUsername(tag))
    .filter(Boolean);
}

export function hasSelectedAccountTags(selectedTags: string[]): boolean {
  return getSelectedAccountUsernames(selectedTags).length > 0;
}

/** 有限平行 + 預設單線程，降低被 Meta 判定為機器人的風險 */
export function resolveScanConcurrency(taskCount: number): number {
  const cap = Math.min(MAX_CONCURRENCY, getBrowserConcurrency());
  return Math.min(Math.max(taskCount, 1), cap);
}

function addTask(
  tasks: ScanTask[],
  seen: Set<string>,
  task: Omit<ScanTask, "id">
) {
  const key = `${task.kind}:${task.query}`;
  if (seen.has(key)) return;
  seen.add(key);
  tasks.push({ ...task, id: key });
}

const PLACEMENT_QUERY_PREFIX_RE = /^(請問|想問|有人|大家|想知道|想請教|求助|請益)/;
const PLACEMENT_QUERY_MAX = 8;

/** 將研究地圖的問題／支柱轉成 Threads 可搜尋的關鍵字 */
export function normalizePlacementSearchPhrase(text: string): string {
  return text
    .replace(/[？?！!。．、,，；;：:""''「」【】()（）]/g, "")
    .replace(PLACEMENT_QUERY_PREFIX_RE, "")
    .replace(/\s+/g, "")
    .trim()
    .slice(0, 28);
}

function placementPhraseScore(phrase: string, seedQuery: string): number {
  if (phrase.length < 3) return -1;
  if (phrase.length > 28) return -1;
  let score = phrase.length;
  if (seedQuery && (phrase.includes(seedQuery) || seedQuery.includes(phrase))) score += 6;
  if (/推薦|請益|求助|請問|怎麼|用什麼|哪款|困擾|煩惱|怕|癢|過敏/.test(phrase)) score += 4;
  return score;
}

/** 置入模式：從受眾問題 + 內容支柱自動組搜尋詞（不需手動勾 tag） */
export function resolvePlacementSearchQueries(
  researchMap: ResearchMap | null | undefined,
  seedQuery: string,
  selectedTags: string[] = []
): string[] {
  if (!researchMap) {
    const q = normalizePlacementSearchPhrase(seedQuery);
    return q.length >= 3 ? [q] : [];
  }

  const candidates: Array<{ phrase: string; score: number }> = [];

  const preferredTags = selectedTags.length > 0
    ? selectedTags
    : (researchMap.suggestedTags ?? [])
        .filter((tag) => tag.searchType !== "帳號" && !isAccountTag(tag.tag))
        .map((tag) => tag.tag);
  for (const item of preferredTags) {
    const phrase = normalizePlacementSearchPhrase(item);
    const score = placementPhraseScore(phrase, seedQuery);
    if (score >= 0) candidates.push({ phrase, score: score + 30 });
  }

  for (const item of [...(researchMap.questions ?? []), ...(researchMap.pillars ?? [])]) {
    const phrase = normalizePlacementSearchPhrase(item);
    const score = placementPhraseScore(phrase, seedQuery);
    if (score >= 0) candidates.push({ phrase, score });
  }

  const seed = normalizePlacementSearchPhrase(seedQuery);
  if (seed.length >= 3) {
    candidates.push({ phrase: seed, score: placementPhraseScore(seed, seedQuery) + 2 });
  }

  const seen = new Set<string>();
  const sorted = candidates
    .sort((a, b) => b.score - a.score)
    .filter(({ phrase }) => {
      const key = phrase.toLowerCase();
      if (seen.has(key)) return false;
      seen.add(key);
      return true;
    })
    .slice(0, PLACEMENT_QUERY_MAX);

  return sorted.map((c) => c.phrase);
}

export function hasPlacementSearchSources(
  researchMap: ResearchMap | null | undefined,
  seedQuery = ""
): boolean {
  return resolvePlacementSearchQueries(researchMap, seedQuery).length > 0;
}

export function buildPlacementScanTasks(params: {
  researchMap?: ResearchMap | null;
  seedQuery: string;
  selectedTags?: string[];
}): ScanTask[] {
  const queries = resolvePlacementSearchQueries(
    params.researchMap,
    params.seedQuery,
    params.selectedTags
  );
  const tasks: ScanTask[] = [];
  const seen = new Set<string>();

  for (const query of queries) {
    addTask(tasks, seen, {
      kind: "keyword",
      query,
      label: query,
      limit: 14,
    });
  }

  return tasks;
}

export function buildScanTasks(params: {
  selectedTags: string[];
  researchMap?: ResearchMap | null;
  seedQuery: string;
  topicGoal?: string | null;
  topicLabel?: string;
}): ScanTask[] {
  const { selectedTags, researchMap, seedQuery, topicGoal, topicLabel = seedQuery } = params;
  const placementMode = isPlacementGoal(topicGoal);
  const tagMeta = new Map(
    (researchMap?.suggestedTags ?? []).map((t) => [t.tag, t])
  );
  const tasks: ScanTask[] = [];
  const seen = new Set<string>();

  for (const tag of selectedTags) {
    const meta = tagMeta.get(tag);
    const isAccount =
      isAccountTag(tag) || meta?.searchType === "帳號";

    if (isAccount) {
      if (placementMode) continue;
      const username = normalizeUsername(tag);
      const isApprovedTopicAccount =
        meta?.searchType === "帳號" ||
        (researchMap?.similarAccounts ?? []).some(
          (account) => normalizeUsername(account.username).toLowerCase() === username.toLowerCase()
        );
      // 手動輸入、但未被研究地圖確認為同領域的帳號，不直接整頁爬取。
      if (!isApprovedTopicAccount) continue;
      addTask(tasks, seen, {
        kind: "account",
        query: username,
        label: `@${username}`,
        limit: 15,
      });
      continue;
    }

    // 研究地圖內的標籤已經過專用 AI 與自然搜尋詞驗證，不再要求字面包含完整種子詞。
    // 只有不在研究地圖中的手動標籤，才套用嚴格主題錨點防止跑題。
    const isApprovedResearchTag = Boolean(meta);
    if (
      !isAccountTag(tag) &&
      !isApprovedResearchTag &&
      !isOnTopicTag(tag, { label: topicLabel, query: seedQuery })
    ) {
      continue;
    }

    const isShort = meta?.searchType === "短詞" || tag.length <= 4;
    const isNeedTag =
      meta?.searchIntent === "需求" ||
      meta?.searchIntent === "求助" ||
      meta?.searchIntent === "痛點";
    addTask(tasks, seen, {
      kind: "keyword",
      query: tag,
      label: tag,
      limit: placementMode ? (isNeedTag ? 16 : isShort ? 14 : 12) : isShort ? 15 : 12,
    });
  }

  return tasks;
}

export function pickDefaultSelectedTags(
  researchMap: ResearchMap,
  topicGoal?: string | null
): string[] {
  const tags = researchMap.suggestedTags;
  const shorts = tags.filter((t) => t.searchType === "短詞").map((t) => t.tag);
  const quotes = tags.filter((t) => t.searchType === "語錄").map((t) => t.tag);
  const scenes = tags.filter((t) => t.searchType === "情境").map((t) => t.tag);
  const needTags = tags
    .filter((t) => t.searchIntent === "需求" || t.searchIntent === "求助" || t.searchIntent === "痛點")
    .map((t) => t.tag);
  const acctTags = tags
    .filter((t) => t.searchType === "帳號")
    .map((t) => (t.tag.startsWith("@") ? t.tag : `@${t.tag}`));
  const isPlacement = topicGoal === "placement";

  const picked = isPlacement
    ? [
        ...needTags.slice(0, 6),
        ...scenes.slice(0, 5),
        ...shorts.slice(0, 4),
        ...quotes.slice(0, 1),
      ]
    : [
        ...shorts.slice(0, 4),
        ...scenes.slice(0, 2),
        ...quotes.slice(0, 1),
        ...acctTags.slice(0, 1),
      ];

  const target = isPlacement ? 10 : 8;
  const balanced = [...new Set(picked)];
  const fallbackOrder = [
    ...tags.filter((t) => t.searchType !== "帳號" && !isAccountTag(t.tag)).map((t) => t.tag),
    ...acctTags.slice(0, 2),
  ];
  for (const tag of fallbackOrder) {
    if (balanced.length >= target) break;
    if (!balanced.includes(tag)) balanced.push(tag);
  }
  return balanced.slice(0, target);
}
