import type pg from 'pg';
import type { ShippingRepository } from '../domain/ports.js';

interface ZoneRow {
  id: string;
  postal_code_prefix: string | null;
}
interface MethodRow {
  id: string;
  name: string;
  base_cost_cents: number;
  free_shipping_threshold_cents: number | null;
  max_weight_kg: string | number | null;
  free_shipping_max_weight_kg: string | number | null;
  active: boolean;
}

interface ZoneMatch {
  zoneId: string;
  methods: Array<{
    id: string;
    name: string;
    baseCostCents: number;
    freeShippingThresholdCents: number | null;
    maxWeightKg: number | null;
    freeShippingMaxWeightKg: number | null;
    active: boolean;
  }>;
}

export class PgShippingRepository implements ShippingRepository {
  constructor(private readonly pool: pg.Pool) {}

  async findMatchingZone(country: string, postalCode: string): Promise<ZoneMatch | undefined> {
    const zones = await this.pool.query<ZoneRow>(
      `SELECT id, postal_code_prefix FROM shipping_zones
       WHERE country = $1 AND active = true
         AND (postal_code_prefix IS NULL OR $2 LIKE postal_code_prefix || '%')
       ORDER BY postal_code_prefix NULLS LAST`,
      [country, postalCode],
    );
    if (zones.rows.length === 0) return undefined;
    const best = zones.rows[0];
    if (!best) return undefined;

    const methods = await this.pool.query<MethodRow>(
      `SELECT id, name, base_cost_cents, free_shipping_threshold_cents,
              max_weight_kg, free_shipping_max_weight_kg, active
       FROM shipping_methods WHERE zone_id = $1`,
      [best.id],
    );
    return {
      zoneId: best.id,
      methods: methods.rows.map((row) => ({
        id: row.id,
        name: row.name,
        baseCostCents: row.base_cost_cents,
        freeShippingThresholdCents: row.free_shipping_threshold_cents,
        maxWeightKg: row.max_weight_kg === null ? null : Number(row.max_weight_kg),
        freeShippingMaxWeightKg:
          row.free_shipping_max_weight_kg === null ? null : Number(row.free_shipping_max_weight_kg),
        active: row.active,
      })),
    };
  }
}
