export type ProductPersonalizationField = {
  key: string;
  label: string;
  inputType: "choices" | "select" | "radio" | "text" | "textarea" | "email" | "tel" | "number" | "date" | "image" | "color";
  options: Array<{ label: string; priceCents: number }>;
  helperText: string | null;
  helperImageUrl?: string | null;
  helperImageLabel?: string | null;
  showLabel: boolean;
  placeholder: string | null;
  defaultValue: string | null;
  maxLength: number | null;
  required: boolean;
};

export type CartCustomizationValue = {
  key: string;
  label: string;
  value: string;
  priceCents?: number;
};

export const DEFAULT_CUSTOM_THEME_FIELDS: ProductPersonalizationField[] = [
  {
    key: "custom-theme-text",
    label: "Texte / prénom / message",
    inputType: "textarea",
    options: [],
    helperText: "Indiquez le texte principal à intégrer sur votre création.",
    showLabel: true,
    placeholder: "Ex: Joyeux anniversaire Emma",
    defaultValue: null,
    maxLength: 300,
    required: false,
  },
  {
    key: "custom-theme-primary-color",
    label: "Couleur principale",
    inputType: "color",
    options: [],
    helperText: "Choisissez la couleur dominante de votre thème.",
    showLabel: true,
    placeholder: null,
    defaultValue: "#d7c2a0",
    maxLength: null,
    required: false,
  },
  {
    key: "custom-theme-font",
    label: "Police d'écriture souhaitée",
    inputType: "text",
    options: [],
    helperText: "Ex: manuscrite, élégante, enfantine...",
    showLabel: true,
    placeholder: "Ex: écriture manuscrite",
    defaultValue: null,
    maxLength: 120,
    required: false,
  },
  {
    key: "custom-theme-date",
    label: "Date",
    inputType: "text",
    options: [],
    helperText: "Ajoutez une date ou une période si elle doit apparaître sur le visuel.",
    showLabel: true,
    placeholder: "Ex: 14 juin 2026",
    defaultValue: null,
    maxLength: 120,
    required: false,
  },
  {
    key: "custom-theme-theme",
    label: "Thème souhaité",
    inputType: "textarea",
    options: [],
    helperText: "Décrivez l'univers souhaité : mariage, baptême, voiture, animal, princesse...",
    showLabel: true,
    placeholder: "Ex: jungle pastel avec animaux de la savane",
    defaultValue: null,
    maxLength: 300,
    required: false,
  },
  {
    key: "custom-theme-secondary-color",
    label: "Couleur secondaire",
    inputType: "color",
    options: [],
    helperText: "Ajoutez une seconde couleur si vous souhaitez enrichir la palette.",
    showLabel: true,
    placeholder: null,
    defaultValue: "#f3efe4",
    maxLength: null,
    required: false,
  },
  {
    key: "custom-theme-inspiration",
    label: "Photo d'inspiration",
    inputType: "image",
    options: [],
    helperText: "Ajoutez une image d'inspiration si vous en avez une.",
    showLabel: true,
    placeholder: null,
    defaultValue: null,
    maxLength: null,
    required: false,
  },
];

export function isCustomizationImageValue(value: string) {
  return /^https?:\/\//i.test(value) && /\.(png|jpe?g|webp|heic|heif)(\?.*)?$/i.test(value);
}

export function normalizeCustomizationHexColor(value: string) {
  const normalized = value.trim();
  if (!/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.test(normalized)) {
    return null;
  }

  return normalized.startsWith("#") ? normalized : `#${normalized}`;
}

export function isCustomizationHexColorValue(value: string) {
  return Boolean(normalizeCustomizationHexColor(value));
}

export function resolvePersonalizationInputType(inputType: string) {
  if (inputType === "email" || inputType === "tel" || inputType === "number" || inputType === "date" || inputType === "color") {
    return inputType;
  }

  return "text";
}

function normalizeKey(value: string) {
  return value
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "");
}

function isFieldShape(value: unknown): value is Record<string, unknown> {
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
}

function normalizePriceCents(value: unknown) {
  return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.round(value)) : 0;
}

function isNonNull<T>(value: T | null): value is T {
  return value !== null;
}

export function readProductPersonalizationFields(metadata: Record<string, unknown>): ProductPersonalizationField[] {
  const raw = metadata.personalization_fields;
  if (!Array.isArray(raw)) return [];

  const fields = raw
    .map((item, index) => {
      if (!isFieldShape(item)) return null;

      const label = typeof item.label === "string" ? item.label.trim() : "";
      const keySource =
        typeof item.key === "string" && item.key.trim()
          ? item.key
          : typeof item.slug === "string" && item.slug.trim()
            ? item.slug
            : label || `field-${index + 1}`;
      const key = normalizeKey(keySource);
      const inputType =
        item.inputType === "select" ||
        item.inputType === "radio" ||
        item.inputType === "text" ||
        item.inputType === "textarea" ||
        item.inputType === "email" ||
        item.inputType === "tel" ||
        item.inputType === "number" ||
        item.inputType === "date" ||
        item.inputType === "image" ||
        item.inputType === "color"
          ? item.inputType
          : "choices";
      const options = Array.isArray(item.options)
        ? item.options
            .map((value) => {
              if (typeof value === "string") {
                const label = value.trim();
                return label ? { label, priceCents: 0 } : null;
              }

              if (!isFieldShape(value)) return null;

              const label = typeof value.label === "string" ? value.label.trim() : "";
              if (!label) return null;

              return {
                label,
                priceCents: normalizePriceCents(value.priceCents),
              };
            })
            .filter(isNonNull)
        : [];

      if (!label || !key) return null;
      if ((inputType === "choices" || inputType === "select" || inputType === "radio") && options.length === 0) return null;

      return {
        key,
        label,
        inputType,
        options,
        helperText: typeof item.helperText === "string" ? item.helperText.trim() : null,
        helperImageUrl: typeof item.helperImageUrl === "string" ? item.helperImageUrl.trim() : null,
        helperImageLabel: typeof item.helperImageLabel === "string" ? item.helperImageLabel.trim() : null,
        showLabel: item.showLabel !== false,
        placeholder: typeof item.placeholder === "string" ? item.placeholder.trim() : null,
        defaultValue: typeof item.defaultValue === "string" ? item.defaultValue.trim() : null,
        maxLength: typeof item.maxLength === "number" && Number.isFinite(item.maxLength) ? item.maxLength : null,
        required: item.required === true,
      } satisfies ProductPersonalizationField;
    })
    .filter(isNonNull);

  return fields;
}

export function readLineItemCustomizations(metadata: Record<string, unknown> | null | undefined): CartCustomizationValue[] {
  const source = metadata?.customizations;
  const parsed =
    typeof source === "string"
      ? (() => {
          try {
            return JSON.parse(source) as unknown;
          } catch {
            return null;
          }
        })()
      : source;

  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];

  return Object.entries(parsed as Record<string, unknown>)
    .map(([key, value]) => {
      if (!value || typeof value !== "object" || Array.isArray(value)) return null;
      const label = typeof (value as Record<string, unknown>).label === "string" ? String((value as Record<string, unknown>).label).trim() : "";
      const rawValue = typeof (value as Record<string, unknown>).value === "string" ? String((value as Record<string, unknown>).value).trim() : "";

      if (!label || !rawValue) return null;

      const item: CartCustomizationValue = {
        key,
        label,
        value: rawValue,
        priceCents:
          typeof (value as Record<string, unknown>).priceCents === "number" && Number.isFinite((value as Record<string, unknown>).priceCents)
            ? Math.max(0, Math.round((value as Record<string, unknown>).priceCents as number))
            : undefined,
      };
      return item;
    })
    .filter(isNonNull);
}
