import { z } from "zod";
import type { SearchIntent, SearchTagType, SuggestedTag } from "@/lib/types/research";

const SEARCH_INTENTS = ["痛點", "知識", "經驗", "對比", "工具", "語錄", "需求", "求助"] as const;
const SEARCH_TYPES = ["短詞", "情境", "帳號", "語錄"] as const;

export const researchMapLooseSchema = z.object({
  audienceSummary: z.string().min(1),
  contentGoal: z.string().min(1),
  questions: z.array(z.string()).min(1),
  pillars: z.array(z.string()).min(1),
  suggestedTags: z.array(
    z.object({
      tag: z.string(),
      reason: z.string(),
      searchIntent: z.enum(SEARCH_INTENTS),
      searchType: z.enum(SEARCH_TYPES).optional(),
    })
  ).min(1),
  exclusions: z.array(z.string()).min(1),
});

function asString(value: unknown): string {
  if (typeof value === "string") return value.trim();
  if (typeof value === "number" || typeof value === "boolean") return String(value);
  return "";
}

function asStringArray(value: unknown): string[] {
  if (!Array.isArray(value)) return [];
  return value
    .map((item) => {
      if (typeof item === "string") return item.trim();
      if (item && typeof item === "object" && "text" in item) {
        return asString((item as { text?: unknown }).text);
      }
      return "";
    })
    .filter(Boolean);
}

function normalizeIntent(value: unknown): SearchIntent {
  const raw = asString(value);
  if ((SEARCH_INTENTS as readonly string[]).includes(raw)) return raw as SearchIntent;
  return "知識";
}

function normalizeSearchType(value: unknown, tag: string): SearchTagType | undefined {
  const raw = asString(value);
  if ((SEARCH_TYPES as readonly string[]).includes(raw)) return raw as SearchTagType;
  if (tag.startsWith("@")) return "帳號";
  if (tag.length <= 4) return "短詞";
  if (tag.includes("語錄")) return "語錄";
  if (tag.length <= 8) return "情境";
  return "短詞";
}

function coerceSuggestedTags(value: unknown): SuggestedTag[] {
  if (!Array.isArray(value)) return [];

  const out: SuggestedTag[] = [];
  for (const item of value) {
    if (typeof item === "string") {
      const tag = item.trim().replace(/^@/, "");
      if (!tag) continue;
      out.push({
        tag,
        reason: "AI 建議的搜尋標籤",
        searchIntent: "知識",
        searchType: normalizeSearchType(undefined, tag),
      });
      continue;
    }

    if (!item || typeof item !== "object") continue;
    const obj = item as Record<string, unknown>;
    const tag = asString(obj.tag ?? obj.label ?? obj.name ?? obj.keyword);
    if (!tag) continue;
    const cleanTag = tag.replace(/^@/, "");
    out.push({
      tag: cleanTag,
      reason: asString(obj.reason ?? obj.description ?? obj.why) || "AI 建議的搜尋標籤",
      searchIntent: normalizeIntent(obj.searchIntent ?? obj.intent),
      searchType: normalizeSearchType(obj.searchType ?? obj.type, cleanTag),
    });
  }

  return out;
}

export function extractJsonFromText(text: string): unknown {
  const cleaned = text
    .replace(/```json\s*/gi, "")
    .replace(/```\s*/g, "")
    .trim();

  try {
    return JSON.parse(cleaned);
  } catch {
    const objStart = cleaned.indexOf("{");
    const objEnd = cleaned.lastIndexOf("}");
    if (objStart >= 0 && objEnd > objStart) {
      try {
        return JSON.parse(cleaned.slice(objStart, objEnd + 1));
      } catch {
        /* fall through */
      }
    }
    const arrStart = cleaned.indexOf("[");
    const arrEnd = cleaned.lastIndexOf("]");
    if (arrStart >= 0 && arrEnd > arrStart) {
      try {
        return JSON.parse(cleaned.slice(arrStart, arrEnd + 1));
      } catch {
        /* fall through */
      }
    }
    throw new Error("AI 回傳的不是合法 JSON");
  }
}

export function coerceResearchMapRaw(
  parsed: unknown,
  fallback: { label: string; query: string; brief: string }
): z.infer<typeof researchMapLooseSchema> {
  const root =
    parsed && typeof parsed === "object"
      ? (parsed as Record<string, unknown>)
      : {};

  const nested =
    root.researchMap && typeof root.researchMap === "object"
      ? (root.researchMap as Record<string, unknown>)
      : root;

  const audienceSummary =
    asString(nested.audienceSummary ?? nested.audience ?? nested.受眾) ||
    `關注「${fallback.label}」的 Threads 受眾，想從 ${fallback.query} 相關內容找到共鳴與實用資訊。`;

  const contentGoal =
    asString(nested.contentGoal ?? nested.goal ?? nested.目標) ||
    `產出準確、有故事感的新型小語，服務 ${fallback.query} 主題受眾。`;

  const questions = asStringArray(nested.questions ?? nested.questionsList);
  const pillars = asStringArray(nested.pillars ?? nested.contentPillars);
  const exclusions = asStringArray(nested.exclusions ?? nested.exclude);
  const suggestedTags = coerceSuggestedTags(
    nested.suggestedTags ?? nested.tags ?? nested.searchTags
  );

  const coerced = {
    audienceSummary,
    contentGoal,
    questions: questions.length > 0 ? questions : [`${fallback.query} 相關受眾最常問什麼？`],
    pillars: pillars.length > 0 ? pillars : ["實用知識", "同溫經驗"],
    suggestedTags:
      suggestedTags.length > 0
        ? suggestedTags
        : [
            {
              tag: fallback.query.slice(0, 4) || fallback.label.slice(0, 4),
              reason: "主題種子字衍生的短詞",
              searchIntent: "知識" as const,
              searchType: "短詞" as const,
            },
          ],
    exclusions: exclusions.length > 0 ? exclusions : ["業配硬銷", "未查證偏方"],
  };

  return researchMapLooseSchema.parse(coerced);
}