/**
 * Letter Labels constants & helpers
 *
 * Customizable, bilingual (English / Amharic) labels used by letter templates
 * (To, From, Subject, CC, ...). Each label may carry an optional CSS style
 * object (e.g. underline, bold). Stored under the setting code
 * `letter-labels-text` as a JSON object.
 */

export type LetterLabelKey =
  | "to"
  | "from"
  | "subject"
  | "urgent"
  | "cc"
  | "date"
  | "record"
  | "ref_no"
  | "delegate"
  | "for_your_reference";

/** CSS style map for a single label (kebab-case CSS properties). */
export type LetterLabelStyle = Record<string, string>;

export interface LetterLabelEntry {
  en: string;
  am: string;
  style?: LetterLabelStyle;
}

export type LetterLabelsText = Record<LetterLabelKey, LetterLabelEntry>;

export const LETTER_LABELS_SETTING_CODE = "letter-labels-text";

export const LETTER_LABEL_KEYS: LetterLabelKey[] = [
  "to",
  "from",
  "subject",
  "urgent",
  "cc",
  "date",
  "record",
  "ref_no",
  "delegate",
  "for_your_reference",
];

/**
 * Default labels for every key in English & Amharic. Some stored values include
 * trailing punctuation (Subject:, CC:, Ref No:), others don't (To, From).
 */
export const DEFAULT_LETTER_LABELS: LetterLabelsText = {
  to: { en: "To", am: "ለ" },
  from: { en: "From", am: "ከ" },
  subject: { en: "Subject:", am: "ጉዳዩ:" },
  urgent: { en: "Urgent", am: "አስቸኳይ" },
  cc: { en: "CC:", am: "ግልባጭ:", style: { "text-decoration": "underline" } },
  date: { en: "Date", am: "ቀን" },
  record: { en: "Record", am: "መዝገብ" },
  ref_no: { en: "Ref No:", am: "ቁጥር:" },
  delegate: { en: "Delegate", am: "ተወካይ" },
  for_your_reference: { en: "For your reference", am: "ለመረጃ ያህል" },
};

/** Human-friendly field names for the editor (not the printed label text). */
export const LETTER_LABEL_DISPLAY_NAMES: Record<
  LetterLabelKey,
  { en: string; am: string }
> = {
  to: { en: "To", am: "ለ" },
  from: { en: "From", am: "ከ" },
  subject: { en: "Subject label", am: "የጉዳይ መለያ" },
  urgent: { en: "Urgent", am: "አስቸኳይ" },
  cc: { en: "CC", am: "ግልባጭ" },
  date: { en: "Date", am: "ቀን" },
  record: { en: "Record title", am: "የደብዳቤ ርዕስ" },
  ref_no: { en: "Reference number", am: "የማጣቀሻ ቁጥር" },
  delegate: { en: "Delegate / Regarding", am: "ስለ" },
  for_your_reference: { en: "For your reference", am: "እንዲያውቁት" },
};

export const isLetterLabelsSetting = (code: string): boolean =>
  code === LETTER_LABELS_SETTING_CODE;

/** Sidebar section code each label field belongs to. */
export const LETTER_LABEL_CATEGORY_MAP: Record<LetterLabelKey, string> = {
  record: "reference-number",
  ref_no: "reference-number",
  date: "reference-number",
  subject: "subject",
  urgent: "subject",
  to: "receiver",
  from: "receiver",
  delegate: "body",
  cc: "cc",
  for_your_reference: "cc",
};

export type LetterLabelSectionCode =
  | "reference-number"
  | "subject"
  | "receiver"
  | "body"
  | "cc";

/** Normalize API / sidebar section codes to the canonical label section. */
export function normalizeLabelSectionCode(
  sectionCode: string,
): LetterLabelSectionCode | null {
  const lower = sectionCode.trim().toLowerCase();
  if (!lower) return null;

  if (
    lower.includes("reference-number") ||
    lower.includes("reference_number") ||
    lower.includes("referencenumber") ||
    lower === "reference" ||
    (lower.includes("reference") && lower.includes("number")) ||
    lower.includes("record-number") ||
    lower.includes("record_number")
  ) {
    return "reference-number";
  }
  if (lower.includes("subject")) return "subject";
  if (
    lower.includes("receiver") ||
    lower.includes("recipient") ||
    lower === "receivers"
  ) {
    return "receiver";
  }
  if (lower.includes("body") || lower.includes("content")) return "body";
  if (lower.includes("cc")) return "cc";

  return null;
}

const labelMatchesSettingCode = (
  labelKey: LetterLabelKey,
  settingCode: string,
): boolean => {
  const lower = settingCode.trim().toLowerCase();
  if (!lower) return false;

  switch (labelKey) {
    case "to":
      return (
        (/receiver|recipient|^letter-to\b/i.test(lower) ||
          lower.includes("receiver-list")) &&
        !/from|collaborator|sender|cc/i.test(lower)
      );
    case "from":
      return /from|collaborator|sender/i.test(lower);
    case "subject":
      return /subject/i.test(lower) && !/urgent/i.test(lower);
    case "urgent":
      return /urgent/i.test(lower);
    case "record":
      return /record/i.test(lower) && !/ref/i.test(lower);
    case "ref_no":
      return /ref/i.test(lower) && /no|number/i.test(lower);
    case "date":
      return /date/i.test(lower);
    case "delegate":
      return /delegate|regarding/i.test(lower) || lower.includes("body");
    case "cc":
      return (
        /letter-cc/i.test(lower) &&
        !/list|prefix|suffix|receiver|for-your-reference|foryourreference/i.test(
          lower,
        )
      );
    case "for_your_reference":
      return /for-your-reference|foryourreference/i.test(lower);
    default:
      return false;
  }
};

export function getLetterLabelKeysForCategory(
  categoryCode: string,
  settingCodes: string[] = [],
): LetterLabelKey[] {
  const canonical = normalizeLabelSectionCode(categoryCode);
  const matched = new Set<LetterLabelKey>();

  if (canonical) {
    for (const key of LETTER_LABEL_KEYS) {
      if (LETTER_LABEL_CATEGORY_MAP[key] === canonical) {
        matched.add(key);
      }
    }
  }

  for (const settingCode of settingCodes) {
    for (const key of LETTER_LABEL_KEYS) {
      if (labelMatchesSettingCode(key, settingCode)) {
        matched.add(key);
      }
    }
  }

  return LETTER_LABEL_KEYS.filter((key) => matched.has(key));
}

const isPlainObject = (value: unknown): value is Record<string, unknown> =>
  typeof value === "object" && value !== null && !Array.isArray(value);

/**
 * Validates a CSS style object, keeping only non-empty string values.
 * Returns undefined when nothing valid remains.
 */
export const normalizeLabelStyle = (
  value: unknown,
): LetterLabelStyle | undefined => {
  if (!isPlainObject(value)) return undefined;
  const out: LetterLabelStyle = {};
  for (const [key, raw] of Object.entries(value)) {
    if (key === "font-size") continue;
    if (typeof raw === "string" && raw.trim() !== "") out[key] = raw;
  }
  return Object.keys(out).length > 0 ? out : undefined;
};

/**
 * Merges an incoming (possibly partial / invalid) value with the defaults so the
 * result always has all keys with valid en/am strings. Preserves style objects.
 */
export const normalizeLetterLabelsValue = (value: unknown): LetterLabelsText => {
  const input = isPlainObject(value) ? value : {};
  const result = {} as LetterLabelsText;

  for (const key of LETTER_LABEL_KEYS) {
    const def = DEFAULT_LETTER_LABELS[key];
    const raw = isPlainObject(input[key]) ? (input[key] as Record<string, unknown>) : {};
    const en = typeof raw.en === "string" ? raw.en : def.en;
    const am = typeof raw.am === "string" ? raw.am : def.am;
    const style = normalizeLabelStyle(raw.style) ?? def.style;
    result[key] = style ? { en, am, style } : { en, am };
  }

  return result;
};
