import {
  parsePhoneNumberFromString,
  isValidPhoneNumber,
  getCountryCallingCode,
  type CountryCode,
  type PhoneNumber,
} from "libphonenumber-js";

/** E.164: optional leading `+`, up to 15 digits (ITU-T). */
export const E164_MAX_DIGITS = 15;
export const E164_MAX_LENGTH = E164_MAX_DIGITS + 1;
/** Comfortable formatted typing limit in the UI (not storage). */
export const PHONE_UI_MAX_LENGTH = 25;

const regionDisplay = new Intl.DisplayNames(["en"], { type: "region" });

export function getCountryLabel(code: CountryCode): string {
  try {
    return regionDisplay.of(code) ?? code;
  } catch {
    return code;
  }
}

/** Strip decorative characters; keep leading `+` and digits only. */
export function sanitizePhoneInput(raw: string): string {
  const trimmed = raw.trim();
  if (!trimmed) return "";
  const hasPlus = trimmed.startsWith("+");
  const digits = trimmed.replace(/\D/g, "");
  if (!digits) return hasPlus ? "+" : "";
  return hasPlus ? `+${digits}` : digits;
}

export function parsePhone(
  value: string,
  defaultCountry?: CountryCode,
): PhoneNumber | undefined {
  const sanitized = sanitizePhoneInput(value);
  if (!sanitized) return undefined;
  return parsePhoneNumberFromString(sanitized, defaultCountry);
}

/** Returns `+{country}{national}` or `undefined` if not a valid number. */
export function normalizeToE164(
  value: string,
  defaultCountry?: CountryCode,
): string | undefined {
  const parsed = parsePhone(value, defaultCountry);
  if (!parsed?.isValid()) return undefined;
  return parsed.format("E.164");
}

/**
 * Best-effort E.164 for the value the user is typing.
 *
 * Returns the strictly-valid E.164 when the number is complete and valid;
 * otherwise returns `+<callingCode><digits>` so partial/invalid input is
 * preserved in form state (and surfaced by validation) instead of being
 * silently reset to an empty string. Returns `""` only when no digits exist.
 */
export function toBestEffortE164(
  value: string,
  defaultCountry: CountryCode,
): string {
  const strict = normalizeToE164(value, defaultCountry);
  if (strict) return strict;

  const digits = value.replace(/\D/g, "");
  if (!digits) return "";

  try {
    return `+${getCountryCallingCode(defaultCountry)}${digits}`;
  } catch {
    return `+${digits}`;
  }
}

export function isValidE164Phone(value: string): boolean {
  const sanitized = sanitizePhoneInput(value);
  if (!sanitized) return false;
  return isValidPhoneNumber(sanitized);
}

export function formatPhoneForDisplay(
  e164: string,
  defaultCountry?: CountryCode,
): { country: CountryCode; national: string } | null {
  const parsed = parsePhone(e164, defaultCountry);
  if (!parsed) return null;
  return {
    country: parsed.country ?? defaultCountry ?? "US",
    national: parsed.formatNational(),
  };
}

export function splitE164ForEditing(
  e164: string | undefined,
  fallbackCountry: CountryCode = "US",
): { country: CountryCode; national: string } {
  if (!e164?.trim()) {
    return { country: fallbackCountry, national: "" };
  }
  const display = formatPhoneForDisplay(e164, fallbackCountry);
  if (display) return display;
  return { country: fallbackCountry, national: e164.replace(/^\+\d{1,3}\s*/, "") };
}
