import { describe, expect, it } from "vitest";
import {
  validateFlockQuoteInput,
  defaultFlockPickupDate,
} from "@/modules/flock/validation";
import { ValidationError } from "@/modules/quote/types";
import { kgToLb, toAxelWholePounds } from "@/modules/quote/unit-converter";

function baseBody(overrides: Record<string, unknown> = {}) {
  return {
    request_id: "550e8400-e29b-41d4-a716-446655440000",
    customer_id: "CUST_001",
    flock_input: {
      pickup_date: defaultFlockPickupDate(),
      pickup_zip: "90001",
      delivery_zip: "75201",
      pallet_count: 6,
      total_weight: { value: 3500, unit: "lb" },
      dimensions: { length: 48, width: 40, height: 48, unit: "in" },
      ...overrides,
    },
  };
}

describe("validateFlockQuoteInput", () => {
  it("接受合法英制入参", () => {
    const parsed = validateFlockQuoteInput(baseBody());
    expect(parsed.palletCount).toBe(6);
    expect(parsed.totalWeightLb).toBe(3500);
    expect(parsed.lengthIn).toBe(48);
  });

  it("500kg 换算为 1103lb（小数进一）", () => {
    expect(toAxelWholePounds(kgToLb(500))).toBe(1103);
    const parsed = validateFlockQuoteInput(
      baseBody({ total_weight: { value: 500, unit: "kg" } }),
    );
    expect(parsed.totalWeightLb).toBe(1103);
  });

  it("0.5t 换算为 1103lb（小数进一）", () => {
    const parsed = validateFlockQuoteInput(
      baseBody({ total_weight: { value: 0.5, unit: "t" } }),
    );
    expect(parsed.totalWeightLb).toBe(1103);
  });

  it("拒绝 ton/tons 歧义单位", () => {
    expect(() =>
      validateFlockQuoteInput(
        baseBody({ total_weight: { value: 0.5, unit: "ton" } }),
      ),
    ).toThrow(/歧义/);
  });

  it("1.2m 尺寸换算并向上取整", () => {
    const parsed = validateFlockQuoteInput(
      baseBody({
        dimensions: { length: 1.2, width: 1, height: 1, unit: "m" },
      }),
    );
    expect(parsed.lengthIn).toBe(48);
    expect(parsed.widthIn).toBe(40);
    expect(parsed.heightIn).toBe(40);
  });

  it("托盘数越界返回中文提示", () => {
    expect(() =>
      validateFlockQuoteInput(baseBody({ pallet_count: 3 })),
    ).toThrow(ValidationError);
    expect(() =>
      validateFlockQuoteInput(baseBody({ pallet_count: 3 })),
    ).toThrow(/4 到 20/);
    expect(() =>
      validateFlockQuoteInput(baseBody({ pallet_count: 21 })),
    ).toThrow(/4 到 20/);
  });

  it("总重超 45000lb 拒绝", () => {
    expect(() =>
      validateFlockQuoteInput(
        baseBody({ total_weight: { value: 45001, unit: "lb" } }),
      ),
    ).toThrow(/45000/);
  });

  it("尺寸超限拒绝", () => {
    expect(() =>
      validateFlockQuoteInput(
        baseBody({
          dimensions: { length: 637, width: 40, height: 48, unit: "in" },
        }),
      ),
    ).toThrow(/636/);
    expect(() =>
      validateFlockQuoteInput(
        baseBody({
          dimensions: { length: 48, width: 103, height: 48, unit: "in" },
        }),
      ),
    ).toThrow(/102/);
    expect(() =>
      validateFlockQuoteInput(
        baseBody({
          dimensions: { length: 48, width: 40, height: 109, unit: "in" },
        }),
      ),
    ).toThrow(/108/);
  });

  it("线性英尺超拖车拒绝（对应官网 Linear feet 报错）", () => {
    expect(() =>
      validateFlockQuoteInput(
        baseBody({
          pallet_count: 18,
          dimensions: { length: 403, width: 102, height: 108, unit: "in" },
        }),
      ),
    ).toThrow(/占用车长|挂车长度/);
  });

  it("缺少 ZIP 提示中文", () => {
    expect(() =>
      validateFlockQuoteInput(baseBody({ pickup_zip: "" })),
    ).toThrow(/提货邮编/);
  });

  it("提货日期早于今天拒绝", () => {
    const d = new Date();
    d.setDate(d.getDate() - 1);
    const mm = String(d.getMonth() + 1).padStart(2, "0");
    const dd = String(d.getDate()).padStart(2, "0");
    const yyyy = d.getFullYear();
    expect(() =>
      validateFlockQuoteInput(
        baseBody({ pickup_date: `${mm}/${dd}/${yyyy}` }),
      ),
    ).toThrow(/不能早于今天/);
  });

  it("提货日期为周末拒绝", () => {
    const d = new Date();
    d.setHours(12, 0, 0, 0);
    const day = d.getDay();
    const daysUntilSat = day === 6 ? 7 : (6 - day + 7) % 7 || 7;
    d.setDate(d.getDate() + daysUntilSat);
    const mm = String(d.getMonth() + 1).padStart(2, "0");
    const dd = String(d.getDate()).padStart(2, "0");
    const yyyy = d.getFullYear();
    expect(() =>
      validateFlockQuoteInput(
        baseBody({ pickup_date: `${mm}/${dd}/${yyyy}` }),
      ),
    ).toThrow(/周六或周日/);
  });

  it("登录态调度字段透传", () => {
    const parsed = validateFlockQuoteInput(
      baseBody({
        form_mode: "logged_in_quick",
        pallet_count: 2,
        total_weight: { value: 6000, unit: "lb" },
        pickup_service: "during_window",
        pickup_window_start_time: "8:00 am",
        pickup_window_end_time: "5:00 pm",
        delivery_service: "must_arrive_by",
        delivery_must_arrive_by_date: "2026-08-01",
        call_for_delivery_appointment: true,
        pickup_location_type: "residential",
        delivery_location_type: "limited_farm",
      }),
    );
    expect(parsed.formMode).toBe("logged_in_quick");
    expect(parsed.pickupService).toBe("during_window");
    expect(parsed.pickupWindowStartTime).toBe("8:00 am");
    expect(parsed.deliveryService).toBe("must_arrive_by");
    expect(parsed.deliveryMustArriveByDate).toBe("2026-08-01");
    expect(parsed.callForDeliveryAppointment).toBe(true);
    expect(parsed.pickupLocationType).toBe("residential");
  });

  it("接受可选 registration 块", () => {
    const parsed = validateFlockQuoteInput(
      baseBody({
        registration: {
          email: "test@qq.com",
          phone: "7536407420",
          first_name: "Li",
        },
      }),
    );
    expect(parsed.registration?.email).toBe("test@qq.com");
    expect(parsed.registration?.phone).toBe("7536407420");
    expect(parsed.registration?.firstName).toBe("Li");
  });

  it("无效邮箱拒绝", () => {
    expect(() =>
      validateFlockQuoteInput(
        baseBody({ registration: { email: "not-an-email" } }),
      ),
    ).toThrow(/工作邮箱/);
  });

  it("无效电话拒绝", () => {
    expect(() =>
      validateFlockQuoteInput(
        baseBody({ registration: { phone: "123" } }),
      ),
    ).toThrow(/10 位/);
  });
});
