/**
 * Variable Format Utilities
 *
 * Format presets and formatting functions for date and number inline variables.
 * Uses Intl.DateTimeFormat and Intl.NumberFormat for locale-aware formatting.
 */

import type { CollectionFieldType } from '@/types';
import { isDateFieldType } from '@/lib/collection-field-utils';

// ─── Date Format Presets ────────────────────────────────────────────

export interface DateFormatPreset {
  id: string;
  label: string;
  options: Intl.DateTimeFormatOptions;
  locale?: string;
}

export interface FormatPresetSection<T> {
  title: string;
  presets: T[];
}

export const DATE_FORMAT_SECTIONS: FormatPresetSection<DateFormatPreset>[] = [
  {
    title: 'Date and time',
    presets: [
      {
        id: 'datetime-long',
        label: 'March 26, 2026, 9:38 AM',
        options: { month: 'long', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true },
      },
      {
        id: 'datetime-short',
        label: 'Mar 26, 2026, 9:38 AM',
        options: { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true },
      },
      {
        id: 'datetime-24h',
        label: 'Mar 26, 2026, 09:38',
        options: { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit', hour12: false },
      },
    ],
  },
  {
    title: 'Date',
    presets: [
      {
        id: 'date-long',
        label: 'March 26, 2026',
        options: { month: 'long', day: 'numeric', year: 'numeric' },
      },
      {
        id: 'date-short',
        label: 'Mar 26, 2026',
        options: { month: 'short', day: 'numeric', year: 'numeric' },
      },
      {
        id: 'date-full',
        label: 'Thursday, March 26, 2026',
        options: { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' },
      },
      {
        id: 'date-short-weekday',
        label: 'Thu, Mar 26, 2026',
        options: { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' },
      },
      {
        id: 'date-us',
        label: '3/26/2026',
        options: { month: 'numeric', day: 'numeric', year: 'numeric' },
        locale: 'en-US',
      },
      {
        id: 'date-eu',
        label: '26/03/2026',
        options: { day: '2-digit', month: '2-digit', year: 'numeric' },
        locale: 'en-GB',
      },
      {
        id: 'date-eu-dot',
        label: '26.03.2026',
        options: { day: '2-digit', month: '2-digit', year: 'numeric' },
        locale: 'de-DE',
      },
      {
        id: 'date-iso',
        label: '2026-03-26',
        options: { year: 'numeric', month: '2-digit', day: '2-digit' },
        locale: 'sv-SE',
      },
      {
        id: 'date-month-year',
        label: 'March 2026',
        options: { month: 'long', year: 'numeric' },
      },
      {
        id: 'date-short-month-year',
        label: 'Mar 2026',
        options: { month: 'short', year: 'numeric' },
      },
      {
        id: 'date-day-month',
        label: '26 Mar',
        options: { day: 'numeric', month: 'short' },
      },
    ],
  },
  {
    title: 'Time',
    presets: [
      {
        id: 'time-12h',
        label: '9:38 AM',
        options: { hour: 'numeric', minute: '2-digit', hour12: true },
      },
      {
        id: 'time-24h',
        label: '09:38',
        options: { hour: '2-digit', minute: '2-digit', hour12: false },
      },
    ],
  },
];

/** Sections for date_only fields (excludes datetime and time presets) */
export const DATE_ONLY_FORMAT_SECTIONS: FormatPresetSection<DateFormatPreset>[] =
  DATE_FORMAT_SECTIONS.filter(s => s.title === 'Date');

/** Flat list of all date presets (used for lookup by ID) */
export const DATE_FORMAT_PRESETS: DateFormatPreset[] =
  DATE_FORMAT_SECTIONS.flatMap(s => s.presets);

// ─── Number Format Presets ──────────────────────────────────────────

export interface NumberFormatPreset {
  id: string;
  label: string;
  options: Intl.NumberFormatOptions;
  locale?: string;
  sample: number;
}

export interface NumberFormatSection {
  title: string;
  presets: NumberFormatPreset[];
}

export const NUMBER_FORMAT_SECTIONS: NumberFormatSection[] = [
  {
    title: 'Standard',
    presets: [
      {
        id: 'number-integer',
        label: '12,345',
        options: { maximumFractionDigits: 0, useGrouping: true },
        sample: 12345,
      },
      {
        id: 'number-decimal',
        label: '12,345.00',
        options: { minimumFractionDigits: 2, maximumFractionDigits: 2, useGrouping: true },
        sample: 12345,
      },
      {
        id: 'number-single-decimal',
        label: '12,345.0',
        options: { minimumFractionDigits: 1, maximumFractionDigits: 1, useGrouping: true },
        sample: 12345,
      },
      {
        id: 'number-plain',
        label: '12345',
        options: { maximumFractionDigits: 0, useGrouping: false },
        sample: 12345,
      },
      {
        id: 'number-plain-decimal',
        label: '12345.00',
        options: { minimumFractionDigits: 2, maximumFractionDigits: 2, useGrouping: false },
        sample: 12345,
      },
      {
        id: 'number-compact',
        label: '12K',
        options: { notation: 'compact', maximumFractionDigits: 1 },
        sample: 12345,
      },
    ],
  },
  {
    title: 'Percent',
    presets: [
      {
        id: 'number-percent',
        label: '12%',
        options: { style: 'percent', maximumFractionDigits: 0 },
        sample: 0.12,
      },
      {
        id: 'number-percent-decimal',
        label: '12.35%',
        options: { style: 'percent', minimumFractionDigits: 2, maximumFractionDigits: 2 },
        sample: 0.1235,
      },
    ],
  },
];

/** Flat list of all number presets (used for lookup by ID) */
export const NUMBER_FORMAT_PRESETS: NumberFormatPreset[] =
  NUMBER_FORMAT_SECTIONS.flatMap(s => s.presets);

// ─── Helpers ────────────────────────────────────────────────────────

const datePresetMap = new Map(DATE_FORMAT_PRESETS.map(p => [p.id, p]));
const numberPresetMap = new Map(NUMBER_FORMAT_PRESETS.map(p => [p.id, p]));

/** Check whether a field type supports format selection */
export function isFormattableFieldType(fieldType: string | null | undefined): boolean {
  return isDateFieldType(fieldType) || fieldType === 'number';
}

/** Get format preset sections for a field type (grouped with titles) */
export function getFormatSectionsForFieldType(
  fieldType: string | null | undefined
): FormatPresetSection<DateFormatPreset | NumberFormatPreset>[] {
  if (fieldType === 'date') return DATE_FORMAT_SECTIONS;
  if (fieldType === 'date_only') return DATE_ONLY_FORMAT_SECTIONS;
  if (fieldType === 'number') return NUMBER_FORMAT_SECTIONS;
  return [];
}

/** Get the default format ID for a field type */
export function getDefaultFormatId(fieldType: string | null | undefined): string | undefined {
  if (isDateFieldType(fieldType)) return 'date-long';
  if (fieldType === 'number') return 'number-integer';
  return undefined;
}

/** Build a field variable data object with the appropriate default format preset */
export function buildFieldVariableData(
  fieldId: string,
  relationshipPath: string[],
  fieldType: CollectionFieldType | null,
  source?: string,
  layerId?: string,
) {
  const defaultFormat = getDefaultFormatId(fieldType);
  return {
    type: 'field' as const,
    data: {
      field_id: fieldId,
      field_type: fieldType,
      relationships: relationshipPath,
      ...(defaultFormat && { format: defaultFormat }),
      ...(source && { source: source as 'page' | 'collection' }),
      ...(layerId && { collection_layer_id: layerId }),
    },
  };
}

/**
 * Format a date value using a preset ID
 * Falls back to the default display format if preset is not found
 */
export function formatDateWithPreset(
  value: string | Date,
  presetId: string | undefined,
  timezone: string = 'UTC'
): string {
  const dateObj = typeof value === 'string' ? new Date(value) : value;
  if (isNaN(dateObj.getTime())) return '';

  const preset = presetId ? datePresetMap.get(presetId) : datePresetMap.get('date-long');
  if (!preset) {
    return new Intl.DateTimeFormat('en-US', {
      timeZone: timezone,
      month: 'long',
      day: 'numeric',
      year: 'numeric',
    }).format(dateObj);
  }

  try {
    return new Intl.DateTimeFormat(preset.locale || 'en-US', {
      timeZone: timezone,
      ...preset.options,
    }).format(dateObj);
  } catch {
    return '';
  }
}

/**
 * Format a number value using a preset ID
 * Falls back to plain string conversion if preset is not found
 */
export function formatNumberWithPreset(
  value: number,
  presetId: string | undefined
): string {
  const preset = presetId ? numberPresetMap.get(presetId) : undefined;
  if (!preset) return String(value);

  try {
    return new Intl.NumberFormat(preset.locale || 'en-US', preset.options).format(value);
  } catch {
    return String(value);
  }
}

/**
 * Generate a live preview label for a date format preset using the current date
 */
export function getDateFormatPreview(preset: DateFormatPreset): string {
  try {
    return new Intl.DateTimeFormat(preset.locale || 'en-US', {
      ...preset.options,
    }).format(new Date());
  } catch {
    return preset.label;
  }
}

/**
 * Generate a live preview label for a number format preset
 */
export function getNumberFormatPreview(preset: NumberFormatPreset): string {
  try {
    return new Intl.NumberFormat(preset.locale || 'en-US', preset.options).format(preset.sample);
  } catch {
    return preset.label;
  }
}
