/**
 * Tử Vi Số · Bát Trạch (8 mansions) feng shui engine
 *
 * Computes:
 *   - Cung mệnh (life-trigram) from year + gender via Lạc Thư Cửu Cung
 *   - Đông/Tây tứ mệnh group
 *   - 8 directional fortunes per cung mệnh (4 cát, 4 hung)
 *   - Recommended ngũ-hành colors
 *
 * Pure TypeScript, no I/O — used by /phong-thuy-nha page and /api callers.
 *
 * Algorithm reference: traditional Bát Trạch (八宅) — same one used by
 * mainstream Vietnamese feng shui texts (Tả Ao, Thẩm Trúc Nhưng).
 *
 * Year semantics: we accept the user's solar (Tây lịch) birth year.
 * The strict version of Bát Trạch uses the "Lunar New Year" boundary —
 * users born before Lập Xuân (~Feb 4) of year Y should use Y-1. We surface
 * this caveat in the UI rather than silently shifting, because the user
 * can correct it themselves with a single click.
 */

export type Bagua = "Khảm" | "Khôn" | "Chấn" | "Tốn" | "Càn" | "Đoài" | "Cấn" | "Ly";

export type Element = "Kim" | "Mộc" | "Thủy" | "Hỏa" | "Thổ";

export type DirectionKey =
  | "Bắc"
  | "Đông Bắc"
  | "Đông"
  | "Đông Nam"
  | "Nam"
  | "Tây Nam"
  | "Tây"
  | "Tây Bắc";

export type Fortune =
  | "Sinh Khí"
  | "Diên Niên"
  | "Thiên Y"
  | "Phục Vị"
  | "Tuyệt Mệnh"
  | "Ngũ Quỷ"
  | "Lục Sát"
  | "Họa Hại";

export type Group = "Đông Tứ Mệnh" | "Tây Tứ Mệnh";

export type DirectionAnalysis = {
  direction: DirectionKey;
  fortune: Fortune;
  isAuspicious: boolean;
  meaning: string;
};

export type FengShuiResult = {
  inputYear: number;
  gender: "Nam" | "Nữ";
  cungMenh: Bagua;
  group: Group;
  element: Element;
  /** Auspicious directions for the cung (Sinh Khí, Diên Niên, Thiên Y, Phục Vị) */
  goodDirections: DirectionAnalysis[];
  /** Inauspicious directions */
  badDirections: DirectionAnalysis[];
  /** All 8 directions ordered N → NE → ... → NW */
  allDirections: DirectionAnalysis[];
  /** Best house-facing direction (typically Sinh Khí) */
  bestDirection: DirectionAnalysis;
  /** Worst direction — avoid main door / bed head */
  worstDirection: DirectionAnalysis;
  /** Compatible bagua for partners / business — same group */
  compatibleBagua: Bagua[];
  /** Element-based color palette */
  colors: { primary: string[]; supporting: string[]; avoid: string[] };
};

// ───────── 1. Cung mệnh from year + gender ─────────

const CUNG_BY_INDEX: Record<number, Bagua> = {
  1: "Khảm",
  2: "Khôn",
  3: "Chấn",
  4: "Tốn",
  6: "Càn",
  7: "Đoài",
  8: "Cấn",
  9: "Ly",
};

function reduceDigits(n: number): number {
  let v = Math.abs(n);
  while (v > 9) {
    v = String(v)
      .split("")
      .reduce((acc, ch) => acc + Number(ch), 0);
  }
  return v;
}

/**
 * Compute cung mệnh from solar year + gender via Lạc Thư Cửu Cung.
 *
 * Nam: index = 11 - sumDigits(year), wrap 9, "5" maps to 2 (Khôn).
 * Nữ:  index = 4  + sumDigits(year), wrap 9, "5" maps to 8 (Cấn).
 *
 * We accept full 4-digit year. Caller is responsible for the Lập Xuân
 * boundary (use year-1 if born before ~Feb 4).
 */
export function computeCungMenh(year: number, gender: "Nam" | "Nữ"): Bagua {
  if (!Number.isInteger(year) || year < 1900 || year > 2100) {
    throw new Error("Năm sinh phải nằm trong khoảng 1900–2100.");
  }
  const sum = reduceDigits(reduceDigits(year));
  let idx: number;
  if (gender === "Nam") {
    idx = 11 - sum;
    if (idx > 9) idx -= 9;
    if (idx === 5) idx = 2;
  } else {
    idx = 4 + sum;
    while (idx > 9) idx -= 9;
    if (idx === 5) idx = 8;
  }
  const cung = CUNG_BY_INDEX[idx];
  if (!cung) throw new Error(`Internal: invalid cung index ${idx}`);
  return cung;
}

// ───────── 2. Đông / Tây tứ mệnh ─────────

const DONG_TU: Bagua[] = ["Khảm", "Ly", "Chấn", "Tốn"];
const TAY_TU: Bagua[] = ["Càn", "Khôn", "Cấn", "Đoài"];

export function getGroup(cung: Bagua): Group {
  return DONG_TU.includes(cung) ? "Đông Tứ Mệnh" : "Tây Tứ Mệnh";
}

// ───────── 3. Element of each bagua ─────────

const ELEMENT_OF: Record<Bagua, Element> = {
  Càn: "Kim",
  Đoài: "Kim",
  Khôn: "Thổ",
  Cấn: "Thổ",
  Chấn: "Mộc",
  Tốn: "Mộc",
  Khảm: "Thủy",
  Ly: "Hỏa",
};

// ───────── 4. Direction × Cung Mệnh table (Bát Trạch) ─────────

/**
 * Standard Bát Trạch table. Row = cung mệnh, column = compass direction,
 * cell = which of the 8 fortunes that direction carries.
 *
 * Source: classic Bát Trạch Minh Kính (八宅明镜) — Việt-hóa standard table
 * found in any Vietnamese phong thủy reference.
 */
const FORTUNE_TABLE: Record<Bagua, Record<DirectionKey, Fortune>> = {
  Khảm: {
    Bắc: "Phục Vị",
    "Đông Bắc": "Ngũ Quỷ",
    Đông: "Thiên Y",
    "Đông Nam": "Sinh Khí",
    Nam: "Diên Niên",
    "Tây Nam": "Tuyệt Mệnh",
    Tây: "Họa Hại",
    "Tây Bắc": "Lục Sát",
  },
  Ly: {
    Bắc: "Diên Niên",
    "Đông Bắc": "Họa Hại",
    Đông: "Sinh Khí",
    "Đông Nam": "Thiên Y",
    Nam: "Phục Vị",
    "Tây Nam": "Lục Sát",
    Tây: "Ngũ Quỷ",
    "Tây Bắc": "Tuyệt Mệnh",
  },
  Chấn: {
    Bắc: "Thiên Y",
    "Đông Bắc": "Lục Sát",
    Đông: "Phục Vị",
    "Đông Nam": "Diên Niên",
    Nam: "Sinh Khí",
    "Tây Nam": "Họa Hại",
    Tây: "Tuyệt Mệnh",
    "Tây Bắc": "Ngũ Quỷ",
  },
  Tốn: {
    Bắc: "Sinh Khí",
    "Đông Bắc": "Tuyệt Mệnh",
    Đông: "Diên Niên",
    "Đông Nam": "Phục Vị",
    Nam: "Thiên Y",
    "Tây Nam": "Ngũ Quỷ",
    Tây: "Lục Sát",
    "Tây Bắc": "Họa Hại",
  },
  Càn: {
    Bắc: "Lục Sát",
    "Đông Bắc": "Thiên Y",
    Đông: "Ngũ Quỷ",
    "Đông Nam": "Họa Hại",
    Nam: "Tuyệt Mệnh",
    "Tây Nam": "Diên Niên",
    Tây: "Sinh Khí",
    "Tây Bắc": "Phục Vị",
  },
  Khôn: {
    Bắc: "Tuyệt Mệnh",
    "Đông Bắc": "Sinh Khí",
    Đông: "Họa Hại",
    "Đông Nam": "Ngũ Quỷ",
    Nam: "Lục Sát",
    "Tây Nam": "Phục Vị",
    Tây: "Thiên Y",
    "Tây Bắc": "Diên Niên",
  },
  Cấn: {
    Bắc: "Ngũ Quỷ",
    "Đông Bắc": "Phục Vị",
    Đông: "Lục Sát",
    "Đông Nam": "Tuyệt Mệnh",
    Nam: "Họa Hại",
    "Tây Nam": "Sinh Khí",
    Tây: "Diên Niên",
    "Tây Bắc": "Thiên Y",
  },
  Đoài: {
    Bắc: "Họa Hại",
    "Đông Bắc": "Diên Niên",
    Đông: "Tuyệt Mệnh",
    "Đông Nam": "Lục Sát",
    Nam: "Ngũ Quỷ",
    "Tây Nam": "Thiên Y",
    Tây: "Phục Vị",
    "Tây Bắc": "Sinh Khí",
  },
};

const FORTUNE_MEANING: Record<Fortune, string> = {
  "Sinh Khí":
    "Đại cát — phát tài, công danh thăng tiến, sức khỏe sung mãn. Tốt nhất cho cửa chính.",
  "Diên Niên": "Cát — sống thọ, hôn nhân hoà thuận, quan hệ bền chặt. Tốt cho phòng ngủ.",
  "Thiên Y": "Cát — sức khoẻ tốt, gặp quý nhân, tiêu tan bệnh tật. Tốt cho đầu giường.",
  "Phục Vị": "Tiểu cát — bình an, ổn định, học hành tiến bộ. Tốt cho bàn làm việc / bàn thờ.",
  "Tuyệt Mệnh": "Đại hung — tổn thọ, hao tài, kiện tụng. Tránh đặt cửa chính / giường.",
  "Ngũ Quỷ": "Hung — thị phi, mất của, tiểu nhân. Tránh hướng bếp / cửa.",
  "Lục Sát": "Hung — cãi vã, hôn nhân lục đục, tai nạn. Tránh phòng ngủ.",
  "Họa Hại": "Hung — bệnh tật triền miên, công việc trắc trở. Tránh hướng bếp.",
};

const AUSPICIOUS: Set<Fortune> = new Set(["Sinh Khí", "Diên Niên", "Thiên Y", "Phục Vị"]);

// Order auspicious by strength (Sinh Khí strongest, Phục Vị mildest)
const FORTUNE_RANK: Record<Fortune, number> = {
  "Sinh Khí": 4,
  "Diên Niên": 3,
  "Thiên Y": 2,
  "Phục Vị": 1,
  "Họa Hại": -1,
  "Lục Sát": -2,
  "Ngũ Quỷ": -3,
  "Tuyệt Mệnh": -4,
};

const ALL_DIRECTIONS: DirectionKey[] = [
  "Bắc",
  "Đông Bắc",
  "Đông",
  "Đông Nam",
  "Nam",
  "Tây Nam",
  "Tây",
  "Tây Bắc",
];

// ───────── 5. Element-based color palette ─────────

const COLORS_BY_ELEMENT: Record<
  Element,
  { primary: string[]; supporting: string[]; avoid: string[] }
> = {
  Kim: {
    primary: ["Trắng", "Bạc", "Vàng kim"],
    supporting: ["Vàng đất", "Nâu đất"], // Thổ sinh Kim
    avoid: ["Đỏ", "Hồng", "Tím"], // Hỏa khắc Kim
  },
  Mộc: {
    primary: ["Xanh lá", "Xanh ngọc"],
    supporting: ["Đen", "Xanh nước biển"], // Thủy sinh Mộc
    avoid: ["Trắng", "Bạc", "Vàng kim"], // Kim khắc Mộc
  },
  Thủy: {
    primary: ["Đen", "Xanh dương đậm", "Xanh navy"],
    supporting: ["Trắng", "Bạc"], // Kim sinh Thủy
    avoid: ["Vàng đất", "Nâu đất"], // Thổ khắc Thủy
  },
  Hỏa: {
    primary: ["Đỏ", "Hồng", "Tím", "Cam"],
    supporting: ["Xanh lá", "Xanh ngọc"], // Mộc sinh Hỏa
    avoid: ["Đen", "Xanh nước biển"], // Thủy khắc Hỏa
  },
  Thổ: {
    primary: ["Vàng đất", "Nâu", "Cam đất"],
    supporting: ["Đỏ", "Hồng", "Tím"], // Hỏa sinh Thổ
    avoid: ["Xanh lá", "Xanh ngọc"], // Mộc khắc Thổ
  },
};

// ───────── 6. Public API ─────────

export type FengShuiInput = {
  year: number;
  gender: "Nam" | "Nữ";
};

export function analyzeFengShui(input: FengShuiInput): FengShuiResult {
  const cung = computeCungMenh(input.year, input.gender);
  const group = getGroup(cung);
  const element = ELEMENT_OF[cung];
  const row = FORTUNE_TABLE[cung];

  const allDirections: DirectionAnalysis[] = ALL_DIRECTIONS.map((dir) => {
    const fortune = row[dir];
    return {
      direction: dir,
      fortune,
      isAuspicious: AUSPICIOUS.has(fortune),
      meaning: FORTUNE_MEANING[fortune],
    };
  });

  const goodDirections = allDirections
    .filter((d) => d.isAuspicious)
    .sort((a, b) => FORTUNE_RANK[b.fortune] - FORTUNE_RANK[a.fortune]);

  const badDirections = allDirections
    .filter((d) => !d.isAuspicious)
    .sort((a, b) => FORTUNE_RANK[a.fortune] - FORTUNE_RANK[b.fortune]);

  const compatibleBagua = (group === "Đông Tứ Mệnh" ? DONG_TU : TAY_TU).filter((b) => b !== cung);

  return {
    inputYear: input.year,
    gender: input.gender,
    cungMenh: cung,
    group,
    element,
    goodDirections,
    badDirections,
    allDirections,
    bestDirection: goodDirections[0],
    worstDirection: badDirections[0],
    compatibleBagua,
    colors: COLORS_BY_ELEMENT[element],
  };
}

// Exposed for testing only
export const _internal = {
  reduceDigits,
  ELEMENT_OF,
  FORTUNE_TABLE,
  ALL_DIRECTIONS,
  AUSPICIOUS,
};
