import { Prisma } from "@jorgecuadros/database";

export function renewalLetterSelect(generation: number) {
  return Prisma.validator<Prisma.PolicySelect>()({
    id: true,
    policyNumber: true,
    policyTo: true,
    netPremium: true,
    policyFee: true,
    total: true,
    currency: true,
    coveragesJson: true,
    customer: {
      select: {
        // Needed by the notification log's customerId FK, not by the letter.
        id: true,
        name: true,
        nameMissing: true,
        email: true,
        phone: true,
        mobile: true,
        addressLine1: true,
        addressLine2: true,
        city: true,
        state: true,
        zipCode: true,
        country: true,
      },
    },
    policyType: { select: { name: true } },
    insuranceProvider: { select: { name: true } },
    vehicles: {
      take: 1,
      select: {
        make: true,
        model: true,
        modelYear: true,
        bodyType: true,
        engineNumber: true,
        licensePlate: true,
      },
    },
    renewalNotices: {
      where: { generation },
      select: { sentAt: true, channel: true },
    },
  });
}

export type RenewalLetterPolicy = Prisma.PolicyGetPayload<{
  select: ReturnType<typeof renewalLetterSelect>;
}>;

export interface RenewalLetterRow extends Record<string, unknown> {
  __kind: "letter";
  policyId: string;
  policyNumber: string;
  policyType: string;
  customerName: string;
  customerEmail: string | null;
  customerPhone: string | null;
  customerMobile: string | null;
  customerAddress: string[];
  provider: string;
  policyTo: string;
  netPremium: string | null;
  policyFee: string | null;
  total: string | null;
  currency: string;
  coverageDays: unknown;
  cslLimit: unknown;
  medicalCoverage: unknown;
  propertyDamage: unknown;
  perPersonLiability: unknown;
  additionalService: unknown;
  vehicle: {
    make: string | null;
    model: string | null;
    modelYear: string | null;
    bodyType: string | null;
    engineNumber: string | null;
    licensePlate: string | null;
  } | null;
  generation: number;
  sentAt: string | null;
}

export function toRenewalLetterRow(
  policy: RenewalLetterPolicy,
  generation: number,
): RenewalLetterRow {
  const notice = policy.renewalNotices[0];
  const coverage = (policy.coveragesJson ?? {}) as Record<string, unknown>;
  const address = [
    policy.customer.addressLine1,
    policy.customer.addressLine2,
    [policy.customer.city, policy.customer.state, policy.customer.zipCode]
      .filter(Boolean)
      .join(", "),
    policy.customer.country,
  ].filter((part): part is string => Boolean(part));

  return {
    __kind: "letter",
    policyId: policy.id,
    policyNumber: policy.policyNumber,
    policyType: policy.policyType?.name ?? "—",
    customerName: policy.customer.nameMissing ? "(sin nombre)" : policy.customer.name,
    customerEmail: policy.customer.email,
    customerPhone: policy.customer.phone,
    customerMobile: policy.customer.mobile,
    customerAddress: address,
    provider: policy.insuranceProvider?.name ?? "—",
    policyTo: policy.policyTo ? policy.policyTo.toISOString().slice(0, 10) : "—",
    netPremium: policy.netPremium ? policy.netPremium.toFixed(2) : null,
    policyFee: policy.policyFee ? policy.policyFee.toFixed(2) : null,
    total: policy.total ? policy.total.toFixed(2) : null,
    currency: policy.currency,
    coverageDays: coverage.cobertura ?? null,
    cslLimit: coverage.csl_limite ?? null,
    medicalCoverage: coverage.gastos_medico ?? null,
    propertyDamage: coverage.propiedades ?? null,
    perPersonLiability: coverage.personas ?? null,
    additionalService:
      coverage.servicio_adicional ?? coverage.servicio_adiconal ?? null,
    vehicle: policy.vehicles[0]
      ? {
          make: policy.vehicles[0].make,
          model: policy.vehicles[0].model,
          modelYear: policy.vehicles[0].modelYear,
          bodyType: policy.vehicles[0].bodyType,
          engineNumber: policy.vehicles[0].engineNumber,
          licensePlate: policy.vehicles[0].licensePlate,
        }
      : null,
    generation,
    sentAt: notice?.sentAt
      ? notice.sentAt.toISOString().slice(0, 10)
      : null,
  };
}
