import type { ResearchMap } from "@/lib/types/research";

export interface ContentBandInput {
  questions: string[];
  pillars: string[];
  exclusions: string[];
}

export interface ContentBandScore {
  score: number;
  inBand: boolean;
  excluded: boolean;
  exclusionHit?: string;
  matchedQuestions: string[];
  matchedPillars: string[];
  reason: string;
}

const PARTICLE_RE = /^[的了嗎呢吧啊有在是不與及或但而這那]/;

function normalizeText(text: string): string {
  return text.replace(/\s+/g, "").trim();
}

function significantSubstrings(phrase: string, minLen = 2, maxLen = 6): string[] {
  const p = normalizeText(phrase);
  if (p.length < minLen) return [];
  const found = new Set<string>();
  if (p.length <= maxLen) {
    found.add(p);
  }
  for (let len = Math.min(maxLen, p.length); len >= minLen; len--) {
    for (let i = 0; i <= p.length - len; i++) {
      const sub = p.slice(i, i + len);
      if (PARTICLE_RE.test(sub)) continue;
      found.add(sub);
    }
  }
  return [...found].sort((a, b) => b.length - a.length);
}

function overlapScore(text: string, phrase: string): number {
  const t = normalizeText(text);
  const p = normalizeText(phrase);
  if (!t || !p) return 0;
  if (t.includes(p)) return Math.min(12, p.length + 2);

  let score = 0;
  for (const sub of significantSubstrings(p)) {
    if (t.includes(sub)) score += sub.length;
  }
  return Math.min(10, score);
}

function bestMatches(text: string, items: string[], minScore = 3): string[] {
  return items
    .map((item) => ({ item, score: overlapScore(text, item) }))
    .filter((x) => x.score >= minScore)
    .sort((a, b) => b.score - a.score)
    .map((x) => x.item);
}

export function scoreContentBand(text: string, band: ContentBandInput): ContentBandScore {
  const t = text.trim();
  if (!t) {
    return {
      score: -10,
      inBand: false,
      excluded: false,
      matchedQuestions: [],
      matchedPillars: [],
      reason: "內容為空",
    };
  }

  for (const ex of band.exclusions) {
    const term = ex.trim();
    if (term.length >= 2 && t.includes(term)) {
      return {
        score: -100,
        inBand: false,
        excluded: true,
        exclusionHit: term,
        matchedQuestions: [],
        matchedPillars: [],
        reason: `觸及排除項目：${term}`,
      };
    }
  }

  const matchedQuestions = bestMatches(t, band.questions);
  const matchedPillars = bestMatches(t, band.pillars);

  const questionScore = matchedQuestions.reduce((sum, q) => sum + overlapScore(t, q), 0);
  const pillarScore = matchedPillars.reduce((sum, p) => sum + overlapScore(t, p), 0);
  const score = questionScore * 1.15 + pillarScore;

  const inBand = matchedQuestions.length > 0 || matchedPillars.length > 0;

  let reason = "";
  if (!inBand) {
    reason = "未呼應受眾問題或內容支柱";
  } else {
    const parts: string[] = [];
    if (matchedQuestions.length > 0) {
      parts.push(`呼應問題：${matchedQuestions[0]}`);
    }
    if (matchedPillars.length > 0) {
      parts.push(`符合支柱：${matchedPillars[0]}`);
    }
    reason = parts.join("；");
  }

  return {
    score,
    inBand,
    excluded: false,
    matchedQuestions,
    matchedPillars,
    reason,
  };
}

export function isInContentBand(
  text: string,
  band: ContentBandInput,
  minScore = 3
): boolean {
  const result = scoreContentBand(text, band);
  if (result.excluded) return false;
  return result.inBand && result.score >= minScore;
}

export function contentBandFromResearchMap(
  map: Pick<ResearchMap, "questions" | "pillars" | "exclusions"> | null | undefined
): ContentBandInput | null {
  if (!map) return null;
  const questions = map.questions?.filter(Boolean) ?? [];
  const pillars = map.pillars?.filter(Boolean) ?? [];
  const exclusions = map.exclusions?.filter(Boolean) ?? [];
  if (questions.length === 0 && pillars.length === 0) return null;
  return { questions, pillars, exclusions };
}

export function buildContentBandPromptBlock(
  map: Pick<ResearchMap, "questions" | "pillars" | "exclusions"> | null | undefined
): string {
  if (!map) return "";
  const questions = map.questions?.filter(Boolean) ?? [];
  const pillars = map.pillars?.filter(Boolean) ?? [];
  const exclusions = map.exclusions?.filter(Boolean) ?? [];
  if (questions.length === 0 && pillars.length === 0) return "";

  return `【內容區間】貼文必須落在研究地圖定義的範圍內，否則 EXCLUDE：
${
  questions.length > 0
    ? `- 受眾會問什麼（須呼應至少一項痛點／疑問）：\n  ${questions.map((q) => `· ${q}`).join("\n  ")}`
    : ""
}
${
  pillars.length > 0
    ? `- 內容支柱（須符合至少一項方向）：\n  ${pillars.map((p) => `· ${p}`).join("\n  ")}`
    : ""
}
${
  exclusions.length > 0
    ? `- 不要碰（觸及任一項 → 一律 EXCLUDE）：\n  ${exclusions.map((e) => `· ${e}`).join("\n  ")}`
    : ""
}
判定原則：只有「有產品需求」但完全不在上述區間內的貼文 → EXCLUDE；閒聊、晒照、跑題亦 EXCLUDE。`;
}