/**
 * Zod schemas wrapping the i18n primitives. Used by route handlers
 * and form-level validation so the same rules run client + server.
 */

import { z } from 'zod';

import { ISO_COUNTRIES } from '@/lib/i18n/countries';
import { isValidE164 } from '@/lib/i18n/phone';
import { isValidSubdivisionCode } from '@/lib/i18n/subdivisions';

// ─── Country ──────────────────────────────────────────────────────────────────

/** ISO-3166-1 alpha-2, uppercase. */
export const countryIsoSchema = z
  .string()
  .length(2)
  .toUpperCase()
  .refine((c) => ISO_COUNTRIES.has(c), 'Unknown country code');

// ─── Phone ────────────────────────────────────────────────────────────────────

/** E.164 form, e.g. '+442079460958'. */
export const phoneE164Schema = z
  .string()
  .min(1)
  .refine((v) => isValidE164(v), 'Invalid phone number');

// ─── Timezone ─────────────────────────────────────────────────────────────────

/**
 * IANA timezone (e.g. 'Europe/Warsaw'). Validates against
 * `Intl.supportedValuesOf('timeZone')` when available. Older Node
 * runtimes that lack the API fall back to a permissive shape check
 * (`Region/City`) so the validator never blocks the path.
 */
export const ianaTimezoneSchema = z
  .string()
  .min(1)
  .refine((tz) => {
    if (typeof Intl !== 'undefined' && 'supportedValuesOf' in Intl) {
      try {
        const supported = Intl.supportedValuesOf('timeZone') as string[];
        if (supported.length > 0) return supported.includes(tz);
      } catch {
        // fall through
      }
    }
    return /^[A-Z][A-Za-z_+-]+\/[A-Za-z_+-]+/.test(tz);
  }, 'Unknown timezone');

// ─── Subdivision ──────────────────────────────────────────────────────────────

/** ISO 3166-2 code, e.g. 'PL-MZ'. */
export const subdivisionIsoSchema = z
  .string()
  .min(2)
  .refine((code) => isValidSubdivisionCode(code), 'Unknown subdivision code');

// ─── Optional variants ────────────────────────────────────────────────────────
// Inline forms most callers will use - empty strings normalize to null
// so the user clearing a field doesn't fail validation.

export const optionalCountryIsoSchema = z
  .union([z.literal(''), z.null(), countryIsoSchema])
  .transform((v) => (v === '' || v === null ? null : v));

export const optionalPhoneE164Schema = z
  .union([z.literal(''), z.null(), phoneE164Schema])
  .transform((v) => (v === '' || v === null ? null : v));

export const optionalIanaTimezoneSchema = z
  .union([z.literal(''), z.null(), ianaTimezoneSchema])
  .transform((v) => (v === '' || v === null ? null : v));

export const optionalSubdivisionIsoSchema = z
  .union([z.literal(''), z.null(), subdivisionIsoSchema])
  .transform((v) => (v === '' || v === null ? null : v));
