import { nanoid } from "nanoid";

import type {
  CopyOptimizationResult,
  OptimizedArticle,
  QaReport,
} from "../domain/types";
import type {
  CalibrationContext,
  CalibrationDirection,
  CalibrationEvent,
  RubricVersion,
  ScoringRun,
} from "./types";

export const GEO_RUBRIC_V1: RubricVersion = {
  id: "rubric_geo_v1",
  version: "v1",
  name: "GEO article performance rubric",
  formula: "weighted_average_0_to_10",
  is_active: true,
  created_at: "2026-06-24T00:00:00.000Z",
  dimensions: [
    {
      id: "fact_integrity",
      label: "事实一致性",
      weight: 2,
      description: "事实、公司名、产品名和经验年限是否遵守事实卡。",
    },
    {
      id: "platform_fit",
      label: "平台适配",
      weight: 1.5,
      description: "表达是否匹配目标发布平台。",
    },
    {
      id: "search_intent_fit",
      label: "搜索意图匹配",
      weight: 1.5,
      description: "是否回答GEO/Search背后的用户问题。",
    },
    {
      id: "answer_density",
      label: "答案密度",
      weight: 1.5,
      description: "是否提供具体信息而不是泛泛宣传。",
    },
    {
      id: "trust_signal_quality",
      label: "信任信号质量",
      weight: 1.5,
      description: "可信依据是否具体、克制且可复核。",
    },
    {
      id: "readability",
      label: "可读性",
      weight: 1,
      description: "标题、摘要、正文是否清晰易读。",
    },
  ],
};

export const HUMAN_COPY_RUBRIC_V1: RubricVersion = {
  id: "rubric_human_copy_v1",
  version: "v1",
  name: "人味文案优化评分口径",
  dimensions: [
    {
      id: "restraint",
      label: "改动克制",
      weight: 0.2,
      description: "减少机械润色，不把短文案扩写成宣传稿。",
    },
    {
      id: "meaning_fidelity",
      label: "原意保真",
      weight: 0.25,
      description: "保留原文意图、事实和表达边界。",
    },
    {
      id: "natural_tone",
      label: "语气自然度",
      weight: 0.25,
      description: "读起来像真人表达，少套路句和格式痕迹。",
    },
    {
      id: "goal_fit",
      label: "目标匹配",
      weight: 0.15,
      description: "符合优化目标和发布场景。",
    },
    {
      id: "ai_taste_risk",
      label: "AI味风险",
      weight: 0.15,
      description: "宣传腔、套话、聊天痕迹和填充词风险低。",
    },
  ],
  formula: "weighted_average_0_to_10",
  is_active: true,
  created_at: "2026-07-08T00:00:00.000Z",
};

interface ScoreOptimizedArticleInput {
  jobId: string;
  article: OptimizedArticle;
  qaReport: QaReport;
  resultVersionId?: string | null;
}

export function scoreOptimizedArticle({
  jobId,
  article,
  qaReport,
  resultVersionId = null,
}: ScoreOptimizedArticleInput): ScoringRun {
  const combined = `${article.title}\n${article.summary}\n${article.body_markdown}`;
  const dimensionScores = {
    fact_integrity: scoreFactIntegrity(qaReport),
    platform_fit: scoreRuleGroup(qaReport, ["platform_fit", "voice_consistency"]),
    search_intent_fit: hasGeoIntent(combined) ? 4 : 2,
    answer_density: scoreAnswerDensity(combined),
    trust_signal_quality: scoreTrustSignals(combined, qaReport),
    readability: scoreReadability(article),
  };

  return {
    id: `score_${nanoid(10)}`,
    result_version_id: resultVersionId,
    case_type: "article",
    job_id: jobId,
    revision: article.revision ?? 1,
    rubric_version_id: GEO_RUBRIC_V1.id,
    dimension_scores: dimensionScores,
    composite_score: weightedComposite(dimensionScores),
    rationale: buildRationale(dimensionScores),
    created_at: new Date().toISOString(),
  };
}

export function scoreHumanCopyResult({
  resultVersionId,
  result,
}: {
  resultVersionId: string;
  result: CopyOptimizationResult;
}): ScoringRun {
  const warningsPenalty = Math.min(result.warnings.length, 3) * 0.5;
  const aiTasteWarnings = result.ai_taste_checks.filter(
    (check) => check.status === "warn",
  ).length;
  const dimensionScores = {
    restraint: result.optimized_text.length > 280 ? 3 : 5,
    meaning_fidelity: result.change_notes.some(
      (note) => note.confidence === "uncertain",
    )
      ? 3.5
      : 5,
    natural_tone: Math.max(2, 5 - aiTasteWarnings * 0.75),
    goal_fit: 4.5,
    ai_taste_risk: Math.max(1, 5 - aiTasteWarnings - warningsPenalty),
  };

  return {
    id: `score_${nanoid(10)}`,
    result_version_id: resultVersionId,
    case_type: "human_copy",
    job_id: null,
    revision: null,
    rubric_version_id: HUMAN_COPY_RUBRIC_V1.id,
    dimension_scores: dimensionScores,
    composite_score: weightedAverage0To10(HUMAN_COPY_RUBRIC_V1, dimensionScores),
    rationale: "基于改动克制、原意保真、自然度、目标匹配和AI味风险生成评分。",
    created_at: new Date().toISOString(),
  };
}

function scoreFactIntegrity(report: QaReport) {
  const hardRules = ["company_name_integrity", "claim_consistency", "hallucination_risk"];
  const statuses = report.checks
    .filter((check) => hardRules.includes(check.rule_id))
    .map((check) => check.status);
  if (statuses.includes("fail")) return 1;
  if (statuses.includes("warn")) return 4;
  return 5;
}

function scoreRuleGroup(report: QaReport, ruleIds: string[]) {
  const statuses = report.checks
    .filter((check) => ruleIds.includes(check.rule_id))
    .map((check) => check.status);
  if (statuses.includes("fail")) return 2;
  if (statuses.includes("warn")) return 3;
  return 4;
}

function hasGeoIntent(text: string) {
  return /GEO|AI搜索|生成式引擎|搜索|可见性|问答|推荐/i.test(text);
}

function scoreAnswerDensity(text: string) {
  const headings = (text.match(/^##\s+/gm) ?? []).length;
  const concreteSignals = (
    text.match(/服务|流程|方案|能力|团队|行业|客户|案例/g) ?? []
  ).length;
  if (headings >= 2 && concreteSignals >= 8) return 5;
  if (headings >= 1 && concreteSignals >= 4) return 4;
  if (concreteSignals >= 2) return 3;
  return 2;
}

function scoreTrustSignals(text: string, report: QaReport) {
  const hallucination = report.checks.find(
    (check) => check.rule_id === "hallucination_risk",
  );
  if (hallucination?.status === "fail") return 1;
  const trustSignals = (text.match(/依据|经验|资质|案例|事实卡|复核|客户/g) ?? [])
    .length;
  if (hallucination?.status === "warn") return trustSignals >= 2 ? 3 : 2;
  return trustSignals >= 2 ? 4 : 3;
}

function scoreReadability(article: OptimizedArticle) {
  const hasLongSentence = `${article.summary}\n${article.body_markdown}`
    .split(/[。！？.!?]/)
    .some((sentence) => sentence.length > 180);
  if (article.title.length > 42 || hasLongSentence) return 3;
  return 4;
}

function weightedComposite(scores: Record<string, number>) {
  return weightedAverage0To10(GEO_RUBRIC_V1, scores);
}

function weightedAverage0To10(rubric: RubricVersion, scores: Record<string, number>) {
  const totalWeight = rubric.dimensions.reduce(
    (sum, dimension) => sum + dimension.weight,
    0,
  );
  const weighted = rubric.dimensions.reduce(
    (sum, dimension) => sum + (scores[dimension.id] ?? 0) * dimension.weight,
    0,
  );
  return Math.round((weighted / totalWeight) * 2 * 10) / 10;
}

function buildRationale(scores: Record<string, number>) {
  return `事实一致性 ${scores.fact_integrity}/5，平台适配 ${scores.platform_fit}/5，答案密度 ${scores.answer_density}/5，信任信号 ${scores.trust_signal_quality}/5。`;
}

export function createCalibrationEvent({
  scoringRun,
  qaReport,
  snapshot,
}: CalibrationContext): CalibrationEvent {
  const direction = inferDirection(scoringRun.composite_score, snapshot.metrics);
  const observations = buildObservations(
    direction,
    scoringRun,
    qaReport,
    snapshot.feedback_summary,
  );

  return {
    id: `cal_${nanoid(10)}`,
    publication_id: snapshot.publication_id,
    scoring_run_id: scoringRun.id,
    performance_snapshot_id: snapshot.id,
    direction,
    observations,
    recommended_action:
      "先积累至少 5 篇同类样本，再评估是否调整 GEO rubric 权重。",
    created_at: new Date().toISOString(),
  };
}

function inferDirection(
  composite: number,
  metrics: { views?: number; clicks?: number; inquiries?: number },
): CalibrationDirection {
  if (!metrics.views && !metrics.clicks && !metrics.inquiries) {
    return "needs_more_data";
  }
  if ((metrics.inquiries ?? 0) >= 3 || (metrics.clicks ?? 0) >= 50) {
    return "better_than_expected";
  }
  if ((metrics.views ?? 0) < 100 && composite >= 7) {
    return "worse_than_expected";
  }
  return "as_expected";
}

function buildObservations(
  direction: CalibrationDirection,
  scoringRun: ScoringRun,
  qaReport: QaReport,
  feedbackSummary: string,
) {
  const observations = [
    `综合评分 ${scoringRun.composite_score}/10，真实表现方向为 ${direction}。`,
  ];
  if (qaReport.overall_status !== "pass") {
    observations.push(`QA 状态为 ${qaReport.overall_status}，需要和表现数据一起复盘。`);
  }
  if (feedbackSummary) {
    observations.push(`反馈摘要：${feedbackSummary}`);
  }
  if ((scoringRun.dimension_scores.trust_signal_quality ?? 0) <= 3) {
    observations.push("信任信号质量偏低，后续观察是否影响询盘。");
  }
  return observations;
}
