import { z } from "zod";
import { CARGO_TYPES } from "@/modules/quote/validation";
import {
  normalizeDimUnit,
  normalizeWeightUnit,
  weightUnitAmbiguousMessage,
} from "@/modules/quote/unit-converter";

const US_ZIP_REGEX = /^\d{5}(-\d{4})?$/;

const addressDraftSchema = z.object({
  street: z.string().min(1, "请填写街道地址"),
  city: z.string().min(1, "请填写城市"),
  state: z.string().length(2, "请填写 2 位州码"),
  zip: z
    .string()
    .refine((v) => v === "" || US_ZIP_REGEX.test(v), "邮编格式无效")
    .optional()
    .default(""),
});

const apiWeightUnitSchema = z
  .string({ errorMap: () => ({ message: "请选择有效的重量单位" }) })
  .superRefine((s, ctx) => {
    const ambiguous = weightUnitAmbiguousMessage(s);
    if (ambiguous) {
      ctx.addIssue({ code: z.ZodIssueCode.custom, message: ambiguous });
      return;
    }
    if (normalizeWeightUnit(s) === null) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        message: "请选择有效的重量单位（lb / kg / t）",
      });
    }
  })
  .transform((s) => normalizeWeightUnit(s)!);

const apiDimUnitSchema = z
  .string({ errorMap: () => ({ message: "请选择有效的尺寸单位" }) })
  .refine(
    (s) => normalizeDimUnit(s) !== null,
    "请选择有效的尺寸单位（in / cm / m）",
  )
  .transform((s) => normalizeDimUnit(s)!);

const positiveFinite = (label: string) =>
  z
    .number({ invalid_type_error: `请填写${label}` })
    .finite(`请填写有效的${label}`)
    .positive(`请填写有效的${label}`);

const cargoSchema = z.object({
  weight: z.object({
    value: positiveFinite("重量"),
    unit: apiWeightUnitSchema,
  }),
  dimensions: z.object({
    length: positiveFinite("长度"),
    width: positiveFinite("宽度"),
    height: positiveFinite("高度"),
    unit: apiDimUnitSchema,
  }),
  pallet_count: z
    .number({ invalid_type_error: "请填写托盘数" })
    .finite("请填写有效的托盘数")
    .int("请填写有效的托盘数"),
  cargo_type: z.enum(CARGO_TYPES),
});

const candidateSchema = z.object({
  option_id: z.string().min(1),
  display_label: z.string().min(1),
  formatted_address: z.string().min(1),
  street: z.string().min(1),
  city: z.string().min(1),
  state: z.string().length(2),
  zip: z.string().optional().default(""),
  selectable: z.boolean().optional(),
  unavailable_reason: z.string().optional(),
});

export const hostCandidatesBodySchema = z.object({
  pickup_address: addressDraftSchema,
  delivery_address: addressDraftSchema,
  cargo: cargoSchema,
});

export const hostSubmitBodySchema = z.object({
  host_session_id: z.string().uuid("会话标识无效"),
  pickup_candidate: candidateSchema,
  delivery_candidate: candidateSchema,
});
