import { format } from 'date-fns';

/** Typed-in or pasted digits → `dd/mm/yyyy` (max 8 digits). */
export function normalizeDdMmYyyyInput(rawValue: string): string {
  const digits = rawValue.replace(/\D/g, '').slice(0, 8);
  if (digits.length <= 2) return digits;
  if (digits.length <= 4) return `${digits.slice(0, 2)}/${digits.slice(2)}`;
  return `${digits.slice(0, 2)}/${digits.slice(2, 4)}/${digits.slice(4)}`;
}

function parseIsoYmdLocal(value: string): Date | null {
  const match = value.trim().match(/^(\d{4})-(\d{2})-(\d{2})$/);
  if (!match) return null;
  const year = Number(match[1]);
  const month = Number(match[2]);
  const day = Number(match[3]);
  const parsed = new Date(year, month - 1, day);
  if (
    parsed.getFullYear() !== year ||
    parsed.getMonth() !== month - 1 ||
    parsed.getDate() !== day
  ) {
    return null;
  }
  return parsed;
}

export function parseDdMmYyyy(value: string): Date | null {
  const match = value.trim().match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
  if (!match) return null;
  const day = Number(match[1]);
  const month = Number(match[2]);
  const year = Number(match[3]);
  const parsed = new Date(year, month - 1, day);
  if (
    parsed.getFullYear() !== year ||
    parsed.getMonth() !== month - 1 ||
    parsed.getDate() !== day
  ) {
    return null;
  }
  return parsed;
}

/** Legacy `yyyy-mm-dd` report field or `dd/mm/yyyy`. */
export function parseFlexibleVnDateString(s: string): Date | null {
  const t = s.trim();
  if (!t) return null;
  const iso = parseIsoYmdLocal(t);
  if (iso) return iso;
  return parseDdMmYyyy(t);
}

export function formatDdMmYyyy(date: Date): string {
  if (Number.isNaN(date.getTime())) return '';
  return format(date, 'dd/MM/yyyy');
}

/** ISO instant / date string → `dd/MM/yyyy` (local). */
export function formatIsoToDdMmYyyy(iso: string | null | undefined): string {
  if (!iso) return '';
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return '';
  return format(date, 'dd/MM/yyyy');
}

export function formatIsoToDdMmYyyyHhMm(iso: string | null | undefined): string {
  if (!iso) return '';
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return '';
  return format(date, 'dd/MM/yyyy HH:mm');
}

export function formatIsoToDdMmYyyyHhMmSs(iso: string | null | undefined): string {
  if (!iso) return '';
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return '';
  return format(date, 'dd/MM/yyyy HH:mm:ss');
}

/** Ngày sinh: paste `yyyy-mm-dd` or type masked `dd/mm/yyyy`. */
export function normalizeDobInputToStored(rawValue: string): string {
  const t = rawValue.trim();
  if (/^\d{4}-\d{2}-\d{2}$/.test(t)) {
    const d = parseIsoYmdLocal(t);
    return d ? formatDdMmYyyy(d) : normalizeDdMmYyyyInput(rawValue);
  }
  return normalizeDdMmYyyyInput(rawValue);
}

/** Show DOB as `dd/mm/yyyy` when JSON still has legacy `yyyy-mm-dd`. */
export function displayDobStoredAsDdMm(stored: string): string {
  const t = stored.trim();
  if (!t) return '';
  if (/^\d{4}-\d{2}-\d{2}$/.test(t)) {
    const d = parseIsoYmdLocal(t);
    return d ? formatDdMmYyyy(d) : t;
  }
  return t;
}

export function toIsoYmdFromDdMmYyyy(value: string): string | null {
  const d = parseDdMmYyyy(value.trim());
  if (!d) return null;
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}

/** `dd/mm/yyyy` or legacy date-only / ISO instant (contribution tab, exports). */
export function parseContributionSubmissionDateInput(input: unknown): Date | null {
  if (input instanceof Date) {
    return Number.isNaN(input.getTime()) ? null : input;
  }
  const s = String(input ?? '').trim();
  if (!s) return null;
  const flex = parseFlexibleVnDateString(s);
  if (flex) return flex;
  const d = new Date(s);
  return Number.isNaN(d.getTime()) ? null : d;
}

/** Single calendar date stored as `yyyy-mm-dd` or `dd/mm/yyyy` → display `dd/mm/yyyy`. */
export function formatVnDateFieldForDisplay(s: string | undefined): string {
  if (!s?.trim()) return '';
  const d = parseFlexibleVnDateString(s);
  return d ? formatDdMmYyyy(d) : s;
}
