export type ImportType = "answers" | "competitors" | "deliveries" | "completion" | "evidence" | "brand_logo";

export type ImportError = {
  row: number;
  field: string;
  message: string;
};

export type ImportValidation = {
  rows: Record<string, string>[];
  validRows: Record<string, string>[];
  errors: ImportError[];
};

export const importDefinitions = {
  answers: {
    label: "AI回答与判定数据",
    required: ["record_id", "prompt_id", "platform", "model_version", "tested_at", "record_status", "keyword", "question_type", "question"],
    columns: ["record_id", "prompt_id", "platform", "model_version", "tested_at", "record_status", "keyword", "question_type", "scene", "region", "question", "answer", "conversation_url", "mention", "recommendation_prompt", "recommend", "top3", "rank", "sentiment", "fact_points_total", "fact_points_correct", "accuracy_note", "judged_by", "citation_detectable", "brand_cited", "citation_urls"],
    example: ["ANS-202609-001", "P001", "DeepSeek", "V3", "2026-09-20 10:30", "valid", "粤式茶楼", "品牌推荐", "商务宴请", "广州", "广州有哪些值得推荐的粤式茶楼？", "示例完整回答", "https://example.com/conversation", "1", "1", "1", "1", "2", "正面", "3", "3", "3个品牌事实点均已核验", "项目审核人", "1", "1", "https://example.com/source"],
  },
  competitors: {
    label: "竞品检测与SOV数据",
    required: ["record_id", "prompt_id", "platform", "competitor_name", "mentioned", "recommended"],
    columns: ["record_id", "prompt_id", "platform", "competitor_name", "mentioned", "recommended", "rank"],
    example: ["ANS-202609-001", "P001", "DeepSeek", "竞品品牌A", "1", "1", "1"],
  },
  deliveries: {
    label: "交付内容与媒体链接",
    required: ["item_id", "title", "media", "original_url"],
    columns: ["item_id", "title", "media", "media_level", "original_url", "publish_date", "index_status", "citation_status", "ai_platforms"],
    example: ["C001", "粤式茶楼文化与城市记忆", "中国发展网", "官方权威媒体", "https://example.com/article", "2026-09-18", "已索引", "检测到引用", "豆包|DeepSeek"],
  },
  completion: {
    label: "合同交付完成度与证据",
    required: ["item_id", "category", "item_name", "unit", "contract_quantity", "qualified_quantity", "weight", "evidence_url"],
    columns: ["item_id", "category", "item_name", "unit", "contract_quantity", "qualified_quantity", "weight", "evidence_url", "note"],
    example: ["D001", "内容建设", "GEO内容", "篇", "60", "60", "25", "https://example.com/delivery-register", "文章清单及成品文件"],
  },
  evidence: {
    label: "HTML／截图证据",
    required: [],
    columns: [],
    example: [],
  },
  brand_logo: {
    label: "品牌Logo",
    required: [],
    columns: [],
    example: [],
  },
} as const;

export function parseDelimited(text: string, delimiter = ",") {
  const rows: string[][] = [];
  let row: string[] = [];
  let cell = "";
  let quoted = false;

  for (let index = 0; index < text.length; index += 1) {
    const char = text[index];
    const next = text[index + 1];
    if (char === '"' && quoted && next === '"') {
      cell += '"';
      index += 1;
    } else if (char === '"') {
      quoted = !quoted;
    } else if (char === delimiter && !quoted) {
      row.push(cell.trim());
      cell = "";
    } else if ((char === "\n" || char === "\r") && !quoted) {
      if (char === "\r" && next === "\n") index += 1;
      row.push(cell.trim());
      if (row.some(Boolean)) rows.push(row);
      row = [];
      cell = "";
    } else {
      cell += char;
    }
  }
  row.push(cell.trim());
  if (row.some(Boolean)) rows.push(row);
  return rows;
}

export function parseStructuredFile(text: string, filename: string) {
  if (filename.toLowerCase().endsWith(".json")) {
    const value = JSON.parse(text) as unknown;
    const source = Array.isArray(value)
      ? value
      : value && typeof value === "object" && Array.isArray((value as { rows?: unknown }).rows)
        ? (value as { rows: unknown[] }).rows
        : [];
    return source.map((item) => {
      if (!item || typeof item !== "object") return {};
      return Object.fromEntries(Object.entries(item).map(([key, entry]) => [key.trim().toLowerCase(), Array.isArray(entry) ? entry.map((value) => String(value).trim()).filter(Boolean).join("|") : String(entry ?? "").trim()]));
    });
  }

  const delimiter = filename.toLowerCase().endsWith(".tsv") ? "\t" : ",";
  const matrix = parseDelimited(text.replace(/^\uFEFF/, ""), delimiter);
  const headers = (matrix.shift() ?? []).map((item) => item.trim().toLowerCase());
  return matrix.map((cells) => Object.fromEntries(headers.map((header, index) => [header, cells[index]?.trim() ?? ""])));
}

export function validateImport(type: "answers" | "competitors" | "deliveries" | "completion", rows: Record<string, string>[]): ImportValidation {
  const definition = importDefinitions[type];
  const errors: ImportError[] = [];
  const validRows: Record<string, string>[] = [];
  const seen = new Set<string>();
  const validFlag = (value: string | undefined) => ["0", "1", "true", "false", "是", "否", "yes", "no", "y", "n"].includes((value ?? "").trim().toLowerCase());

  rows.forEach((row, index) => {
    const rowErrors: ImportError[] = [];
    definition.required.forEach((field) => {
      if (!row[field]) rowErrors.push({ row: index + 2, field, message: "必填字段为空" });
    });
    if (type === "deliveries" && row.original_url && !/^https?:\/\//i.test(row.original_url)) {
      rowErrors.push({ row: index + 2, field: "original_url", message: "必须是以 http:// 或 https:// 开头的链接" });
    }
    if (type === "completion") {
      if (row.evidence_url && !/^https?:\/\//i.test(row.evidence_url)) rowErrors.push({ row: index + 2, field: "evidence_url", message: "交付证据必须是可访问的http://或https://链接" });
      const contractQuantity = Number(row.contract_quantity);
      const qualifiedQuantity = Number(row.qualified_quantity);
      const weight = Number(row.weight);
      if (!Number.isFinite(contractQuantity) || contractQuantity <= 0) rowErrors.push({ row: index + 2, field: "contract_quantity", message: "合同数量必须是大于0的数字" });
      if (!Number.isFinite(qualifiedQuantity) || qualifiedQuantity < 0) rowErrors.push({ row: index + 2, field: "qualified_quantity", message: "合格数量必须是大于或等于0的数字" });
      if (!Number.isFinite(weight) || weight <= 0 || weight > 100) rowErrors.push({ row: index + 2, field: "weight", message: "权重必须是0到100之间的数字" });
    }
    if (type === "answers" && row.conversation_url && !/^https?:\/\//i.test(row.conversation_url)) {
      rowErrors.push({ row: index + 2, field: "conversation_url", message: "对话链接格式无效" });
    }
    if (type === "answers" && row.tested_at && Number.isNaN(Date.parse(row.tested_at))) {
      rowErrors.push({ row: index + 2, field: "tested_at", message: "检测时间格式无效，请使用YYYY-MM-DD HH:mm或ISO时间" });
    }
    if (type === "answers" && row.citation_urls) {
      const invalidCitation = row.citation_urls.split("|").map((url) => url.trim()).find((url) => url && !/^https?:\/\//i.test(url));
      if (invalidCitation) rowErrors.push({ row: index + 2, field: "citation_urls", message: "引用链接必须以http://或https://开头，多条使用|分隔" });
    }
    if (type === "answers") {
      const recordStatus = (row.record_status ?? "").trim().toLowerCase();
      if (!["valid", "failed", "timeout", "invalid"].includes(recordStatus)) {
        rowErrors.push({ row: index + 2, field: "record_status", message: "检测状态仅支持valid、failed、timeout或invalid" });
      }
      if (recordStatus === "valid") {
        for (const field of ["answer", "mention", "recommendation_prompt", "recommend", "top3", "fact_points_total", "fact_points_correct", "accuracy_note", "judged_by", "citation_detectable", "brand_cited"] as const) {
          if (row[field] === undefined || row[field] === "") rowErrors.push({ row: index + 2, field, message: "有效回答必须填写该字段" });
        }
      }
      for (const field of ["mention", "recommendation_prompt", "recommend", "top3", "citation_detectable", "brand_cited"] as const) {
        if (row[field] && !validFlag(row[field])) rowErrors.push({ row: index + 2, field, message: "判定值仅支持1/0、是/否或true/false" });
      }
      if (flag(row.mention) && !row.sentiment) rowErrors.push({ row: index + 2, field: "sentiment", message: "品牌被提及时必须填写情感判定" });
      if (row.sentiment && !["positive", "neutral", "negative", "正面", "中性", "负面"].includes(row.sentiment.trim().toLowerCase())) {
        rowErrors.push({ row: index + 2, field: "sentiment", message: "情感仅支持正面/中性/负面或positive/neutral/negative" });
      }
      if (flag(row.recommend) && !row.rank) rowErrors.push({ row: index + 2, field: "rank", message: "主动推荐时必须填写推荐位次" });
      if (flag(row.top3) && (!flag(row.recommendation_prompt) || !flag(row.recommend) || Number(row.rank) > 3)) {
        rowErrors.push({ row: index + 2, field: "top3", message: "Top3仅可用于推荐型Prompt中已推荐且位次不高于3的回答" });
      }
      if (flag(row.recommendation_prompt) && flag(row.recommend) && Number(row.rank) <= 3 && !flag(row.top3)) {
        rowErrors.push({ row: index + 2, field: "top3", message: "推荐型Prompt中推荐位次不高于3时Top3必须标记为1" });
      }
      const factTotal = Number(row.fact_points_total ?? 0);
      const factCorrect = Number(row.fact_points_correct ?? 0);
      if (recordStatus === "valid" && (!Number.isInteger(factTotal) || factTotal < 0)) rowErrors.push({ row: index + 2, field: "fact_points_total", message: "事实点总数必须是大于或等于0的整数" });
      if (recordStatus === "valid" && (!Number.isInteger(factCorrect) || factCorrect < 0 || factCorrect > factTotal)) rowErrors.push({ row: index + 2, field: "fact_points_correct", message: "正确事实点必须是0到事实点总数之间的整数" });
      if (flag(row.brand_cited) && (!flag(row.citation_detectable) || !row.citation_urls)) {
        rowErrors.push({ row: index + 2, field: "brand_cited", message: "品牌信源被引用时必须支持引用检测并填写实际引用URL" });
      }
    }
    if (type === "competitors") {
      for (const field of ["mentioned", "recommended"] as const) {
        if (row[field] && !validFlag(row[field])) rowErrors.push({ row: index + 2, field, message: "判定值仅支持1/0、是/否或true/false" });
      }
      if (flag(row.recommended) && !row.rank) rowErrors.push({ row: index + 2, field: "rank", message: "竞品被推荐时必须填写推荐位次" });
    }
    if ((type === "answers" || type === "competitors") && row.rank && (!Number.isFinite(Number(row.rank)) || Number(row.rank) <= 0)) {
      rowErrors.push({ row: index + 2, field: "rank", message: "排名必须是大于0的数字" });
    }
    const uniqueKey = type === "answers" ? row.record_id : type === "competitors" ? `${row.record_id}\u001f${row.competitor_name}` : row.item_id;
    if (uniqueKey && seen.has(uniqueKey)) rowErrors.push({ row: index + 2, field: ["deliveries", "completion"].includes(type) ? "item_id" : "record_id", message: "当前文件中存在重复记录ID" });
    if (uniqueKey) seen.add(uniqueKey);
    errors.push(...rowErrors);
    if (!rowErrors.length) validRows.push(row);
  });

  return { rows, validRows, errors };
}

function csvCell(value: string) {
  return `"${value.replaceAll('"', '""')}"`;
}

export function createCsvTemplate(type: "answers" | "competitors" | "deliveries" | "completion", includeExample = false) {
  const definition = importDefinitions[type];
  const example = includeExample ? `${definition.example.map(csvCell).join(",")}\n` : "";
  return `\uFEFF${definition.columns.map(csvCell).join(",")}\n${example}`;
}

export function flag(value: string | undefined) {
  return ["1", "true", "是", "yes", "y"].includes((value ?? "").trim().toLowerCase()) ? 1 : 0;
}
