import { describe, expect, it } from "vitest";

import {
  applyRoundWeightToScore,
  buildScoredRoundCandidates,
  computeSemanticCandidateHitRate,
  mergeScoredCandidates,
  normalizeOfferDetailUrl,
  resolveRoundWeight,
  scoreTitleAgainstQuery,
  type FixedSearchRoundStatus,
} from "./fixed-search-runtime.ts";

describe("normalizeOfferDetailUrl", () => {
  it("removes tracking parameters and keeps the canonical detail URL", () => {
    expect(normalizeOfferDetailUrl("https://detail.1688.com/offer/904426649399.html?spm=a1&foo=bar#top")).toBe(
      "https://detail.1688.com/offer/904426649399.html",
    );
  });

  it("converts offerId-style URLs to canonical detail URLs", () => {
    expect(normalizeOfferDetailUrl("https://s.1688.com/offer_search.htm?offerId=904426649399&spm=a1")).toBe(
      "https://detail.1688.com/offer/904426649399.html",
    );
  });
});

describe("scoreTitleAgainstQuery", () => {
  it("scores by per-character hit ratio after removing spaces", () => {
    expect(scoreTitleAgainstQuery("哈光 隧道地质罗盘", "DQL-8型地质罗盘仪 哈光DQL-8A高精度指南针指北针阻尼式地质罗盘")).toBe(75);
    expect(scoreTitleAgainstQuery("哈光 隧道地质罗盘", "厂家黄铜罗盘罗经仪三合综合盘指南针高精度测方位八卦玄空寻龙")).toBe(25);
  });

  it("treats generated fallback titles as zero-score dirty data", () => {
    expect(scoreTitleAgainstQuery("电磁阀 4V-310-1O", "1688结果-58")).toBe(0);
  });
});

describe("buildScoredRoundCandidates", () => {
  const round: FixedSearchRoundStatus = {
    round: 1,
    label: "主搜索词",
    query: "哈光 隧道地质罗盘",
    status: "success",
    failure_reason: "",
  };

  it("deduplicates URLs inside a round before scoring", () => {
    const scored = buildScoredRoundCandidates({
      round,
      products: [
        {
          title: "DQL-8型地质罗盘仪 哈光DQL-8A高精度指南针指北针阻尼式地质罗盘",
          offerUrl: "https://detail.1688.com/offer/586601372847.html?spm=a1",
        },
        {
          title: "重复商品",
          offer_url: "https://detail.1688.com/offer/586601372847.html#foo",
        },
      ],
    });

    expect(scored).toHaveLength(1);
    expect(scored[0]?.url).toBe("https://detail.1688.com/offer/586601372847.html");
    expect(scored[0]?.score).toBe(60);
  });

  it("applies configured field weights for mixed-field rounds", () => {
    const scored = buildScoredRoundCandidates({
      round: {
        ...round,
        round: 3,
        label: "品牌+标准化名称",
      },
      products: [
        {
          title: "DQL-8型地质罗盘仪 哈光DQL-8A高精度指南针指北针阻尼式地质罗盘",
          offerUrl: "https://detail.1688.com/offer/586601372847.html",
        },
      ],
    });

    // base score 75 * 品牌(1) * 标准化名称(0.6)
    expect(scored[0]?.score).toBe(45);
  });
});

describe("round weight scoring", () => {
  it("resolves fallback weight=1 for unknown round labels", () => {
    expect(resolveRoundWeight("未知组合")).toBe(1);
  });

  it("calculates multiplicative weight by round label", () => {
    expect(resolveRoundWeight("主搜索词")).toBe(0.8);
    expect(resolveRoundWeight("标准化名称+品牌")).toBe(0.6);
    expect(resolveRoundWeight("标准化名称+标准化规格")).toBe(0.24);
    expect(resolveRoundWeight("标准化名称+分类(材质/用途)")).toBe(0.12);
  });

  it("applies weight to score and keeps two decimals", () => {
    expect(applyRoundWeightToScore(99, "标准化名称+标准化规格")).toBe(23.76);
    expect(applyRoundWeightToScore(0, "主搜索词")).toBe(0);
  });
});

describe("mergeScoredCandidates", () => {
  it("keeps the highest-scoring global candidate for the same URL", () => {
    const merged = mergeScoredCandidates([
      {
        input: "词 A",
        "title-text": "标题 A",
        url: "https://detail.1688.com/offer/1.html",
        score: 25,
        search_round: 1,
        round_label: "主搜索词",
        source_product: {
          title: "标题 A",
          offer_url: "https://detail.1688.com/offer/1.html",
          merchant_name: "商家 A",
          merchant_url: "",
          image_url: "",
          wangwang_url: "",
          contact_page_url: "",
          offer_screenshot_path: "",
        },
      },
      {
        input: "词 B",
        "title-text": "标题 B",
        url: "https://detail.1688.com/offer/1.html",
        score: 75,
        search_round: 2,
        round_label: "标准化名称",
        source_product: {
          title: "标题 B",
          offer_url: "https://detail.1688.com/offer/1.html",
          merchant_name: "商家 B",
          merchant_url: "",
          image_url: "",
          wangwang_url: "",
          contact_page_url: "",
          offer_screenshot_path: "",
        },
      },
    ]);

    expect(merged).toHaveLength(1);
    expect(merged[0]?.score).toBe(75);
    expect(merged[0]?.input).toBe("词 B");
  });
});

describe("computeSemanticCandidateHitRate", () => {
  it("calculates matched candidates over judged candidates", () => {
    expect(computeSemanticCandidateHitRate([
      { judge_status: "judged", is_match: true },
      { judge_status: "judged", is_match: true },
      { judge_status: "judged", is_match: true },
      { judge_status: "judged", is_match: false },
      { judge_status: "judged", is_match: false },
      { judge_status: "judged", is_match: false },
      { judge_status: "judged", is_match: false },
      { judge_status: "judged", is_match: false },
      { judge_status: "judged", is_match: false },
      { judge_status: "judged", is_match: false },
    ])).toEqual({
      hit_rate: 0.3,
      matched_count: 3,
      judged_count: 10,
      unjudged_count: 0,
      error_count: 0,
    });
  });

  it("excludes llm errors and skipped candidates from the denominator", () => {
    expect(computeSemanticCandidateHitRate([
      { judge_status: "judged", is_match: true },
      { judge_status: "judged", is_match: false },
      { judge_status: "llm_error", is_match: null },
      { judge_status: "skipped_zero_score", is_match: false },
      { judge_status: "skipped_candidate_limit", is_match: false },
    ])).toEqual({
      hit_rate: 0.5,
      matched_count: 1,
      judged_count: 2,
      unjudged_count: 3,
      error_count: 1,
    });
  });

  it("returns null when no candidate has been judged", () => {
    expect(computeSemanticCandidateHitRate([
      { judge_status: "llm_error", is_match: null },
      { judge_status: "skipped_zero_score", is_match: false },
    ])).toEqual({
      hit_rate: null,
      matched_count: 0,
      judged_count: 0,
      unjudged_count: 2,
      error_count: 1,
    });
  });
});
