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

import {
  buildSearchItemCompletionOutcome,
  isRetryableSearchTaskItemUpdateError,
  retrySearchTaskItemUpdate,
} from "./search-task-completion.ts";

describe("search task completion outcome", () => {
  it("treats a material with at least one final product as completed even when target contacts are short", () => {
    expect(buildSearchItemCompletionOutcome({
      childSucceeded: true,
      finalSelectedProductCount: 1,
      qualifiedResultCount: 1,
      targetResultCount: 5,
      shortageMessage: "搜索完成，有效商家不足：1/5",
    })).toEqual({
      countAsCompleted: true,
      countAsFailed: false,
      status: "completed",
      warningMessage: "搜索完成，有效商家不足：1/5",
    });
  });

  it("treats a material with qualified contacts as completed even when final product counting is unavailable", () => {
    expect(buildSearchItemCompletionOutcome({
      childSucceeded: true,
      finalSelectedProductCount: 0,
      qualifiedResultCount: 1,
      targetResultCount: 5,
      shortageMessage: "搜索完成，有效商家不足：1/5",
    }).status).toBe("completed");
  });

  it("recognizes transient fetch failures as retryable search task item update errors", () => {
    expect(isRetryableSearchTaskItemUpdateError(new TypeError("fetch failed"))).toBe(true);
    expect(isRetryableSearchTaskItemUpdateError(new Error("[search_task_items] 更新失败: fetch failed"))).toBe(true);
    expect(isRetryableSearchTaskItemUpdateError(new Error("[search_task_items] 更新失败: permission denied"))).toBe(false);
  });

  it("retries transient search task item update failures before returning success", async () => {
    let attempts = 0;
    const result = await retrySearchTaskItemUpdate(async () => {
      attempts += 1;
      if (attempts === 1) {
        throw new TypeError("fetch failed");
      }
      return { status: "completed" };
    }, {
      attempts: 3,
      baseDelayMs: 0,
    });

    expect(result).toEqual({ status: "completed" });
    expect(attempts).toBe(2);
  });
});
