import { describe, expect, it } from "vitest";

import {
  resolveTargetCustomer,
  TARGET_CUSTOMER_REQUIRED_MESSAGE,
} from "@/lib/reports/target-customer";
import type { Customer } from "@/lib/types";

/**
 * 確定期間KPIの「対象顧客をどう決めるか」（指示書AK ★段階6★ / §2-1 の決定表）。
 *
 * ★★何を守るためのテストか★★
 *  - ★★候補が2つ以上のときに「静かに1社を選ぶ」ことをしない★★（★落とし穴6★。D-133）—
 *    ★静かに選ぶ実装は例外もテスト失敗も出さない★ので、ここで固定しておく以外に検出手段が無い
 *  - ★`customer_id` が明示されたら顧客マスタを見ない（存在確認をしない）★（期待値表 6-9）
 *  - ★`group_id` の候補は「その傘下だけ」★（別ホールディングスの顧客を混ぜない）
 *
 * ★ルート（HTTPステータス・`details`）側は
 *   `app/api/reports/__tests__/route.test.ts` の「段階6 — 対象顧客の決定」が見る★。
 */

/** 顧客マスタ1行（`db.customers()` の形。★`group_id` は API の形＝`null` 可★。D-011） */
function customer(id: number, groupId: number | null): Customer {
  return { id, customer_name: `屋号${id}`, group_id: groupId };
}

const NONE = { groupId: null, customerId: null };

describe("resolveTargetCustomer（指示書AK §2-1 の決定表）", () => {
  it("customer_id 指定 → その顧客（★顧客マスタを見ない＝存在確認をしない★。6-9）", () => {
    // ★マスタが空でも、存在しないIDでも、そのまま通す★
    expect(resolveTargetCustomer([], { groupId: null, customerId: 999 })).toEqual({
      ok: true,
      customerId: 999,
    });
  });

  it("★customer_id と group_id の同時指定は customer_id が勝つ★（決定表の1行目）", () => {
    const customers = [customer(1, 1), customer(2, 1)];
    // ★傘下2社でも 422 にならない★ — 顧客が名指しされているので「決まらない」状態ではない
    expect(resolveTargetCustomer(customers, { groupId: 1, customerId: 2 })).toEqual({
      ok: true,
      customerId: 2,
    });
  });

  it("group_id 指定・傘下1社 → その顧客（6-6）", () => {
    const customers = [customer(1, 1), customer(2, 2), customer(3, null)];
    expect(resolveTargetCustomer(customers, { groupId: 2, customerId: null })).toEqual({
      ok: true,
      customerId: 2,
    });
  });

  it("★★group_id 指定・傘下2社 → 定まらない。候補は傘下だけ★★（6-7）", () => {
    const customers = [customer(1, 1), customer(2, 1), customer(3, 2)];
    expect(resolveTargetCustomer(customers, { groupId: 1, customerId: null })).toEqual({
      ok: false,
      candidateCustomerIds: [1, 2],
    });
  });

  it("★group_id 指定・傘下0社 → 定まらない（候補は空配列）★（★指示書に明記が無く、起草者が決めた★）", () => {
    const customers = [customer(1, 1)];
    expect(resolveTargetCustomer(customers, { groupId: 9, customerId: null })).toEqual({
      ok: false,
      candidateCustomerIds: [],
    });
  });

  it("どちらも未指定・顧客が1社だけ → その顧客（★P1 はここ★。6-3）", () => {
    expect(resolveTargetCustomer([customer(7, null)], NONE)).toEqual({
      ok: true,
      customerId: 7,
    });
  });

  it("★★どちらも未指定・顧客が2社 → 定まらない（★静かに1社を選ばない★）★★（6-4 / 6-5）", () => {
    const customers = [customer(1, 1), customer(2, 2)];
    expect(resolveTargetCustomer(customers, NONE)).toEqual({
      ok: false,
      candidateCustomerIds: [1, 2],
    });
  });

  it("★どちらも未指定・顧客が0社 → 定まらない★（マスタが空のときに何かを選ばない）", () => {
    expect(resolveTargetCustomer([], NONE)).toEqual({
      ok: false,
      candidateCustomerIds: [],
    });
  });

  it("★`group_id = null`（ホールディングスなし）の顧客は group_id 指定に当たらない★（D-011）", () => {
    const customers = [customer(1, null), customer(2, 1)];
    // ★「所属なしの顧客だけを引く」経路はそもそも存在しない★（API は 1 以上しか受け付けない）
    expect(resolveTargetCustomer(customers, { groupId: 1, customerId: null })).toEqual({
      ok: true,
      customerId: 2,
    });
  });

  it("★422 の文言は指示書AK §2-1 の原文★（言い換えない）", () => {
    expect(TARGET_CUSTOMER_REQUIRED_MESSAGE).toBe(
      "顧客またはグループを指定してください。複数の顧客のデータを合算した数値は出せません。"
    );
  });
});
