/**
 * ============================================================
 * keyword-artifact-generator.ts — 关键词阶段脚本：生成关键词输入/搜索计划/关键词过程文件
 * ============================================================
 */

import "dotenv/config";

import { mkdir, writeFile } from "node:fs/promises";
import path from "node:path";
import process from "node:process";
import { pathToFileURL } from "node:url";

import {
  analyzeProductCombined,
  resolveLlmRuntimeConfig,
  resolveOnlineStandardizationModel,
} from "../standardization/standardization-llm.ts";
import { toAiKeywordAnalysis, toLlmAnalysisResult } from "../standardization/offline-batch-result.ts";
import { buildFixedSearchPlanRows, buildKeywordInputRow, buildSearchPlanRows } from "./keyword-generator.ts";
import { parseCsvFile } from "../core/csv-parser.ts";
import { getStandardizedResultByMaterialId } from "../internal/db.ts";
import type { ParsedProduct, RawCsvRow, KeywordInputRow, SearchPipelineConfig } from "../core/types.ts";

const AUTOMATION_DIR = path.resolve(import.meta.dirname!, "..");
const PROJECT_ROOT = path.resolve(AUTOMATION_DIR, "..");
const CSV_PATH = path.join(PROJECT_ROOT, "原表 .csv");
const OUTPUT_ROOT = path.join(AUTOMATION_DIR, "output", "linked-row-runs");

function nowStamp() {
  return new Date().toISOString().replace(/[:.]/g, "-");
}

function normalizeSpace(value: string) {
  return String(value ?? "").replace(/\s+/g, " ").trim();
}

function parseArgs(argv: string[]) {
  const options = {
    row: 2,
    materialId: "",
  };

  for (const arg of argv) {
    if (!arg.startsWith("--")) {
      continue;
    }

    const [flag, rawValue] = arg.slice(2).split("=", 2);
    const value = rawValue ?? "";

    if (flag === "row" && value) {
      options.row = Number.parseInt(value, 10);
    } else if (flag === "material-id" && value) {
      options.materialId = value;
    }
  }

  if (!options.materialId && (!Number.isInteger(options.row) || options.row <= 0)) {
    throw new Error("参数 --row 必须是大于 0 的整数，例如 --row=2");
  }

  return options;
}

async function ensureDir(dirPath: string) {
  await mkdir(dirPath, { recursive: true });
}

export async function generateKeywordArtifacts(options: { materialId?: string; row?: number; batchId?: string; pipelineConfig?: SearchPipelineConfig }) {
  const startedAt = new Date().toISOString();
  const runIdentifier = options.materialId?.trim() || `row-${String(options.row ?? 2).padStart(3, "0")}`;
  const runDir = path.join(OUTPUT_ROOT, `${runIdentifier}-${nowStamp()}`);
  const keywordInputPath = path.join(runDir, "keyword_input_preview.json");
  const searchPlanPath = path.join(runDir, "search_plan_preview.json");
  const searchRoundStatusPath = path.join(runDir, "search_round_status.json");
  const keywordProcessPath = path.join(runDir, "keyword-process.json");

  await ensureDir(runDir);

  // ── 当有 batchId 时，从 Supabase 读取已标准化的数据 ─────────
  if (options.batchId) {
    const materialId = options.materialId?.trim();
    if (!materialId) {
      throw new Error("batch 模式缺少 material_id");
    }

    const standardizedResult = await getStandardizedResultByMaterialId(options.batchId, materialId);
    if (!standardizedResult) {
      throw new Error(`Supabase standardized_results 中不存在 batch_id=${options.batchId} material_id=${materialId} 的记录`);
    }

    // 直接从 standardized_results 还原搜索输入
    const targetRow: RawCsvRow = {
      发票种类: standardizedResult.invoice_type ?? "",
      名称: standardizedResult.standardized_name ?? standardizedResult.original_name ?? "",
      规格型号: standardizedResult.standardized_spec ?? standardizedResult.original_spec ?? "",
      品牌: standardizedResult.brand ?? "",
      数量: String(standardizedResult.quantity ?? ""),
      单位: standardizedResult.standardized_unit ?? "",
      "备注/附件": standardizedResult.notes ?? "",
      收货地址: standardizedResult.delivery_address ?? "",
    };

    const analysis = {
      material: normalizeSpace(String(standardizedResult.category ?? "")),
      usage: "",
      simplified_spec: normalizeSpace(String(standardizedResult.standardized_spec ?? standardizedResult.original_spec ?? "")),
      brand_term: normalizeSpace(String(standardizedResult.brand ?? "")),
      keyword_parameter_terms: [],
      modifier_terms: [],
      alternative_terms: Array.isArray(standardizedResult.alt_search_terms)
        ? standardizedResult.alt_search_terms.map((item) => normalizeSpace(String(item))).filter(Boolean)
        : [],
    };

    const product: ParsedProduct = {
      material_id: materialId,
      raw: targetRow,
      analysis,
    };

    const suggestedKeyword = normalizeSpace(String(standardizedResult.primary_search_term ?? ""));
    const aiKeywordAnalysis = {
      suggested_keyword: suggestedKeyword,
      alt_search_terms: analysis.alternative_terms,
      alternative_keywords: analysis.alternative_terms,
      product_type: normalizeSpace(String(standardizedResult.product_type ?? "")),
      structure_summary: normalizeSpace(String(standardizedResult.ai_reasoning ?? "")),
      outcome: "success",
      can_search_1688: true,
      failure_reason: "",
      human_fix_hint: "",
      missing_required_fields: [],
    };
    const regeneratedKeywordInputRow = buildKeywordInputRow(product, options.batchId);
    const fixedSearchPlan = options.pipelineConfig?.keywordSearchEnabled === false
      ? { searchPlanRows: [], roundStatuses: [] }
      : buildFixedSearchPlanRows(product, suggestedKeyword, options.batchId, standardizedResult);
    const searchPlanRows = fixedSearchPlan.searchPlanRows;
    const searchRoundStatuses = fixedSearchPlan.roundStatuses;

    const standardizedResultModel = normalizeSpace(String(standardizedResult.llm_model ?? ""))
      || resolveOnlineStandardizationModel();
    const keywordProcess = {
      ai_keyword_analysis: aiKeywordAnalysis,
      report_type: "keyword_process_report",
      started_at: startedAt,
      finished_at: new Date().toISOString(),
      source: "supabase",
      batch_id: options.batchId,
      material_id: materialId,
      row_name: standardizedResult.standardized_name,
      row_spec: standardizedResult.standardized_spec,
      row_brand: standardizedResult.brand,
      llm_model: standardizedResultModel,
      llm_base_url: process.env.LLM_BASE_URL ?? "",
      source_row: targetRow,
      llm_analysis: analysis,
      keyword_input_path: keywordInputPath,
      search_plan_path: searchPlanPath,
      search_round_status_path: searchRoundStatusPath,
      search_plan_preview: searchPlanRows.map((row) => ({
        search_round: row.search_round,
        primary_keyword: row.primary_keyword,
        search_strategy: row.search_strategy,
        keyword_source: row.keyword_source,
        alt_keywords: row.alt_keywords,
      })),
      search_round_status_preview: searchRoundStatuses,
    };

    await writeFile(keywordInputPath, JSON.stringify([regeneratedKeywordInputRow], null, 2), "utf8");
    await writeFile(searchPlanPath, JSON.stringify(searchPlanRows, null, 2), "utf8");
    await writeFile(searchRoundStatusPath, JSON.stringify(searchRoundStatuses, null, 2), "utf8");
    await writeFile(keywordProcessPath, JSON.stringify(keywordProcess, null, 2), "utf8");

    return {
      materialId,
      runDir,
      keywordInputPath,
      searchPlanPath,
      searchRoundStatusPath,
      keywordProcessPath,
      targetRow,
      keywordInputRows: [regeneratedKeywordInputRow] as KeywordInputRow[],
      searchPlanRows,
      searchRoundStatuses,
      analysis,
      aiKeywordAnalysis,
    };
  }

  // ── 无 batchId 时，从本地 CSV 文件读取（原始逻辑）────────────
  const allRows = parseCsvFile(CSV_PATH);
  const rowNumber = options.row ?? 2;
  const targetRow = allRows[rowNumber - 1];

  if (!targetRow) {
    throw new Error(`CSV 不存在第 ${rowNumber} 行，可用范围是 1-${allRows.length}`);
  }

  const standardizationRuntime = await resolveLlmRuntimeConfig("standardization");
  const standardizationModel = resolveOnlineStandardizationModel(standardizationRuntime.model);
  const combinedResult = await analyzeProductCombined(targetRow);
  const analysis = toLlmAnalysisResult(combinedResult);
  const product: ParsedProduct = {
    material_id: options.materialId?.trim() || `local-row-${rowNumber}`,
    raw: targetRow,
    analysis,
  };

  const keywordInputRows = [buildKeywordInputRow(product)];

  const aiKeywordAnalysis = toAiKeywordAnalysis(combinedResult);

  const searchPlanRows = buildSearchPlanRows(product, aiKeywordAnalysis.suggested_keyword);

  const keywordProcess = {
    ai_keyword_analysis: aiKeywordAnalysis,
    report_type: "keyword_process_report",
    started_at: startedAt,
    finished_at: new Date().toISOString(),
    csv_path: CSV_PATH,
    material_id: product.material_id,
    row_name: normalizeSpace(targetRow.名称),
    row_spec: normalizeSpace(targetRow.规格型号),
    row_brand: normalizeSpace(targetRow.品牌),
    llm_model: standardizationModel,
    llm_base_url: standardizationRuntime.baseURL,
    source_row: targetRow,
    llm_analysis: analysis,
    keyword_input_path: keywordInputPath,
    search_plan_path: searchPlanPath,
    search_round_status_path: searchRoundStatusPath,
    search_plan_preview: searchPlanRows.map((row) => ({
      search_round: row.search_round,
      primary_keyword: row.primary_keyword,
      search_strategy: row.search_strategy,
      keyword_source: row.keyword_source,
      alt_keywords: row.alt_keywords,
    })),
    search_round_status_preview: [],
  };

  await writeFile(keywordInputPath, JSON.stringify(keywordInputRows, null, 2), "utf8");
  await writeFile(searchPlanPath, JSON.stringify(searchPlanRows, null, 2), "utf8");
  await writeFile(searchRoundStatusPath, JSON.stringify([], null, 2), "utf8");
  await writeFile(keywordProcessPath, JSON.stringify(keywordProcess, null, 2), "utf8");

  return {
    materialId: product.material_id,
    row: rowNumber,
    runDir,
    keywordInputPath,
    searchPlanPath,
    searchRoundStatusPath,
    keywordProcessPath,
    targetRow,
    keywordInputRows,
    searchPlanRows,
    searchRoundStatuses: [],
    analysis,
    aiKeywordAnalysis,
  };
}

async function main() {
  const options = parseArgs(process.argv.slice(2));
  const result = await generateKeywordArtifacts({ row: options.row, materialId: options.materialId });

  console.log("\n════════════════════ 关键词结果 ════════════════════");
  if (result.row != null) {
    console.log(`  测试行号:             第 ${result.row} 行`);
  }
  console.log(`  物料ID:               ${result.materialId}`);
  console.log(`  商品名称:             ${result.targetRow.名称}`);
  console.log(`  搜索计划轮次:         ${result.searchPlanRows.length}`);
  console.log(`  关键词输入预览:       ${result.keywordInputPath}`);
  console.log(`  搜索计划预览:         ${result.searchPlanPath}`);
  console.log(`  关键词过程:           ${result.keywordProcessPath}`);
  console.log("════════════════════════════════════════════════════\n");
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  main().catch((error) => {
    console.error("\n❌ 关键词阶段执行失败:", error);
    process.exit(1);
  });
}
