import {
  BROAD_TAG_BLOCKLIST,
  buildTopicAnchor,
  scoreTopicRelevance,
  type TopicAnchorInput,
} from "@/lib/topic-anchor";
import { isPlacementGoal } from "@/lib/types/topic-goal";
import type { ResearchMap, SearchIntent, SearchTagType, SuggestedTag } from "@/lib/types/research";

export interface TagNormalizeInput extends TopicAnchorInput {
  topicGoal?: string | null;
}

const FILLER_ONLY = new Set(["心情", "日常", "分享", "語錄", "推薦", "求助", "請益"]);
const MIN_USEFUL_TAGS = 6;

function minTagScore(anchor: ReturnType<typeof buildTopicAnchor>, clean: string): number {
  if (anchor.requiredConcepts.length >= 2) {
    if (clean.length <= 4) return 6;
    return 4;
  }
  return 3;
}

function normalizeTagShape(tag: SuggestedTag, placement: boolean): SuggestedTag {
  const trimmed = tag.tag.trim();
  const clean = trimmed.replace(/^@/, "").trim();
  return {
    tag: trimmed,
    reason: tag.reason.trim() || "AI 建議的搜尋標籤",
    searchIntent:
      tag.searchIntent ?? (placement ? ("需求" as SearchIntent) : ("知識" as SearchIntent)),
    searchType:
      tag.searchType ??
      (trimmed.startsWith("@") ? ("帳號" as SearchTagType) : clean.length <= 4 ? "短詞" : "情境"),
  };
}

export function filterSuggestedTags(
  tags: SuggestedTag[],
  input: TagNormalizeInput
): SuggestedTag[] {
  const anchor = buildTopicAnchor({
    label: input.label,
    query: input.query,
    brief: input.brief,
    exclusions: input.exclusions,
  });
  const placement = isPlacementGoal(input.topicGoal);

  const scored = tags
    .map((t) => normalizeTagShape(t, placement))
    .filter((t) => t.tag.length > 0)
    .map((t) => {
      const clean = t.tag.replace(/^@/, "").trim();
      const score = scoreTopicRelevance(clean, anchor);
      return { tag: t, clean, score };
    })
    .filter(({ clean, score }) => {
      if (!clean) return false;
      if (FILLER_ONLY.has(clean)) return false;
      if (BROAD_TAG_BLOCKLIST.has(clean) && score < 8) return false;
      return score >= 2;
    })
    .sort((a, b) => b.score - a.score);

  const seen = new Set<string>();
  const out: SuggestedTag[] = [];
  for (const { tag, clean, score } of scored) {
    if (score < minTagScore(anchor, clean)) continue;
    const key = tag.tag.toLowerCase();
    if (seen.has(key)) continue;
    seen.add(key);
    out.push(tag);
  }

  // 嚴格門檻不足時，從研究地圖衍生候選補到合理下限；仍排除零相關與泛詞。
  if (out.length < MIN_USEFUL_TAGS) {
    for (const { tag } of scored) {
      if (out.length >= MIN_USEFUL_TAGS) break;
      const key = tag.tag.toLowerCase();
      if (seen.has(key)) continue;
      seen.add(key);
      out.push(tag);
    }
  }

  const compound = input.query.trim();
  if (
    compound.length >= 4 &&
    compound.length <= 8 &&
    !seen.has(compound.toLowerCase()) &&
    scoreTopicRelevance(compound, anchor) >= minTagScore(anchor, compound)
  ) {
    out.unshift({
      tag: compound,
      reason: "主題核心短詞，優先海巡",
      searchIntent: placement ? "需求" : "知識",
      searchType: compound.length <= 4 ? "短詞" : "情境",
    });
  }

  return out.slice(0, 14);
}

export function preserveTagsFromPreviousMap(
  newMap: ResearchMap,
  previousMap: ResearchMap,
  input: TagNormalizeInput
): ResearchMap {
  const seen = new Set(newMap.suggestedTags.map((t) => t.tag.toLowerCase()));
  const carry = previousMap.suggestedTags.filter((t) => !seen.has(t.tag.toLowerCase()));
  if (carry.length === 0) return newMap;

  return {
    ...newMap,
    suggestedTags: filterSuggestedTags([...newMap.suggestedTags, ...carry], input),
  };
}
