import type { BulkUserItem } from "../../../lib/adminApi";

export type HanmacImportEmailStatus =
  | "valid"
  | "suggested"
  | "needsReview"
  | "ruleMismatch"
  | "blockingError";

export type HanmacImportEmailPreview = {
  originalEmail: string;
  suggestedEmail?: string;
  finalEmail: string;
  status: HanmacImportEmailStatus;
  warnings: string[];
  blockingErrors: string[];
  reason?: string;
  localPart?: string;
};

const surnameRomanization: Record<string, string> = {
  한: "han",
  김: "kim",
  이: "lee",
  박: "park",
  최: "choi",
  정: "jung",
  조: "cho",
  강: "kang",
  윤: "yoon",
  장: "jang",
  임: "lim",
  림: "lim",
  신: "shin",
  오: "oh",
  서: "seo",
  권: "kwon",
  황: "hwang",
  안: "ahn",
  송: "song",
  전: "jeon",
  홍: "hong",
  유: "yoo",
  고: "ko",
  문: "moon",
  양: "yang",
  손: "son",
  배: "bae",
  백: "baek",
  허: "heo",
  남: "nam",
  심: "sim",
  노: "noh",
  하: "ha",
  곽: "kwak",
  성: "sung",
  차: "cha",
  주: "joo",
  우: "woo",
  구: "koo",
  민: "min",
  류: "ryu",
  나: "na",
  진: "jin",
  지: "ji",
  엄: "um",
  채: "chae",
  원: "won",
  천: "cheon",
  방: "bang",
  공: "gong",
  현: "hyun",
  함: "ham",
  여: "yeo",
  추: "choo",
  도: "do",
  소: "so",
  석: "seok",
  선: "sun",
  설: "seol",
  마: "ma",
  길: "gil",
  연: "yeon",
  위: "wi",
  표: "pyo",
  명: "myung",
  기: "ki",
  반: "ban",
  라: "ra",
  왕: "wang",
  금: "geum",
  옥: "ok",
  육: "yook",
  인: "in",
  맹: "maeng",
  제: "je",
  모: "mo",
  탁: "tak",
  국: "guk",
  어: "eo",
  은: "eun",
  편: "pyeon",
  용: "yong",
};

const initialRomanization = [
  "g",
  "g",
  "n",
  "d",
  "d",
  "r",
  "m",
  "b",
  "b",
  "s",
  "s",
  "y",
  "j",
  "j",
  "c",
  "k",
  "t",
  "p",
  "h",
];

export function buildKoreanNameEmailBase(name: string) {
  const runes = [...name.trim()].filter((char) => !/\s/.test(char));
  if (runes.length < 2) {
    return { base: "", needsReview: true };
  }

  const surname = surnameRomanization[runes[0]];
  if (!surname) {
    return { base: "", needsReview: true };
  }

  const initials = runes.slice(1).map((char) => romanizedHangulInitial(char));
  if (initials.some((value) => !value)) {
    return { base: "", needsReview: true };
  }

  return { base: `${initials.join("")}${surname}`, needsReview: false };
}

export function matchesSuggestedNameRule(localPart: string, base: string) {
  const normalizedLocalPart = localPart.trim().toLowerCase();
  const normalizedBase = base.trim().toLowerCase();
  if (!normalizedLocalPart || !normalizedBase) {
    return false;
  }
  if (normalizedLocalPart === normalizedBase) {
    return true;
  }
  return new RegExp(`^${escapeRegExp(normalizedBase)}\\d+$`).test(
    normalizedLocalPart,
  );
}

export function buildHanmacImportEmailPreview(
  user: BulkUserItem,
  existingLocalParts: Set<string>,
  batchLocalParts: Set<string>,
): HanmacImportEmailPreview {
  const originalEmail = user.email.trim();
  const split = splitEmailDomain(originalEmail);
  if (!split) {
    return {
      originalEmail,
      finalEmail: originalEmail,
      status: "blockingError",
      warnings: [],
      blockingErrors: ["invalidEmail"],
      reason: "이메일 형식을 확인해 주세요.",
    };
  }

  const usedLocalParts = new Set([
    ...[...existingLocalParts].map((value) => value.toLowerCase()),
    ...[...batchLocalParts].map((value) => value.toLowerCase()),
  ]);
  const { base, needsReview } = buildKoreanNameEmailBase(user.name);
  const warnings: string[] = [];

  if (needsReview) {
    warnings.push("needsReview");
  }

  if (!split.localPart) {
    if (!base) {
      return {
        originalEmail,
        finalEmail: originalEmail,
        status: "blockingError",
        warnings,
        blockingErrors: ["missingLocalPart"],
        reason: "이름으로 이메일 ID를 제안할 수 없습니다.",
      };
    }

    const nextLocalPart = nextAvailableLocalPart(base, usedLocalParts);
    const finalEmail = `${nextLocalPart}@${split.domain}`;
    batchLocalParts.add(nextLocalPart);
    return {
      originalEmail,
      suggestedEmail: finalEmail,
      finalEmail,
      status: "suggested",
      warnings: appendUnique(warnings, "suggested"),
      blockingErrors: [],
      localPart: nextLocalPart,
    };
  }

  const localPart = split.localPart.toLowerCase();
  if (usedLocalParts.has(localPart)) {
    return {
      originalEmail,
      finalEmail: originalEmail,
      status: "blockingError",
      warnings,
      blockingErrors: ["duplicateLocalPart"],
      reason: "한맥가족 내에서 이미 사용 중인 이메일 ID입니다.",
      localPart,
    };
  }

  batchLocalParts.add(localPart);

  if (base && !matchesSuggestedNameRule(localPart, base)) {
    return {
      originalEmail,
      finalEmail: originalEmail,
      status: "ruleMismatch",
      warnings: appendUnique(warnings, "ruleMismatch"),
      blockingErrors: [],
      reason: "권장 이메일 ID 규칙과 다릅니다.",
      localPart,
    };
  }

  return {
    originalEmail,
    finalEmail: originalEmail,
    status: warnings.includes("needsReview") ? "needsReview" : "valid",
    warnings,
    blockingErrors: [],
    localPart,
  };
}

function splitEmailDomain(email: string) {
  const normalized = email.trim().toLowerCase();
  const parts = normalized.split("@");
  if (parts.length !== 2 || !parts[1] || !parts[1].includes(".")) {
    return null;
  }
  return {
    localPart: parts[0],
    domain: parts[1],
  };
}

function romanizedHangulInitial(char: string) {
  const code = char.codePointAt(0);
  if (code === undefined || code < 0xac00 || code > 0xd7a3) {
    return "";
  }
  const index = Math.floor((code - 0xac00) / 588);
  return initialRomanization[index] ?? "";
}

function nextAvailableLocalPart(base: string, usedLocalParts: Set<string>) {
  const normalizedBase = base.trim().toLowerCase();
  if (!usedLocalParts.has(normalizedBase)) {
    return normalizedBase;
  }

  let index = 1;
  while (usedLocalParts.has(`${normalizedBase}${index}`)) {
    index += 1;
  }
  return `${normalizedBase}${index}`;
}

function appendUnique(values: string[], value: string) {
  if (values.includes(value)) {
    return values;
  }
  return [...values, value];
}

function escapeRegExp(value: string) {
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
