/**
 * Tứ Trụ — Bát Tự (8 chữ).
 * 4 trụ × (Can + Chi) = 8 chữ:
 *   1. Trụ năm   (Niên trụ)
 *   2. Trụ tháng (Nguyệt trụ) — can theo công thức 5x + 2 (5 nguyệt thủ)
 *   3. Trụ ngày  (Nhật trụ) — Julian day modulo 60
 *   4. Trụ giờ   (Thời trụ) — can theo nhật can + chi giờ
 *
 * Tính tương đối — không xử lý tiết khí (giả định mỗi tháng âm lịch
 * là một nguyệt-trụ liền). Đủ chính xác cho mục đích hiển thị tham khảo.
 */

const STEMS = ["Giáp", "Ất", "Bính", "Đinh", "Mậu", "Kỷ", "Canh", "Tân", "Nhâm", "Quý"] as const;

const BRANCHES = [
  "Tý",
  "Sửu",
  "Dần",
  "Mão",
  "Thìn",
  "Tỵ",
  "Ngọ",
  "Mùi",
  "Thân",
  "Dậu",
  "Tuất",
  "Hợi",
] as const;

const STEM_ELEMENT: Record<string, string> = {
  Giáp: "Mộc",
  Ất: "Mộc",
  Bính: "Hỏa",
  Đinh: "Hỏa",
  Mậu: "Thổ",
  Kỷ: "Thổ",
  Canh: "Kim",
  Tân: "Kim",
  Nhâm: "Thuỷ",
  Quý: "Thuỷ",
};

const STEM_YIN_YANG: Record<string, "Dương" | "Âm"> = {
  Giáp: "Dương",
  Ất: "Âm",
  Bính: "Dương",
  Đinh: "Âm",
  Mậu: "Dương",
  Kỷ: "Âm",
  Canh: "Dương",
  Tân: "Âm",
  Nhâm: "Dương",
  Quý: "Âm",
};

const BRANCH_HOUR_RANGES: Array<[string, string]> = [
  ["Tý", "23:00 – 00:59"],
  ["Sửu", "01:00 – 02:59"],
  ["Dần", "03:00 – 04:59"],
  ["Mão", "05:00 – 06:59"],
  ["Thìn", "07:00 – 08:59"],
  ["Tỵ", "09:00 – 10:59"],
  ["Ngọ", "11:00 – 12:59"],
  ["Mùi", "13:00 – 14:59"],
  ["Thân", "15:00 – 16:59"],
  ["Dậu", "17:00 – 18:59"],
  ["Tuất", "19:00 – 20:59"],
  ["Hợi", "21:00 – 22:59"],
];

export type Pillar = {
  stem: string;
  branch: string;
  napAm?: string;
  element: string;
  yinYang: "Dương" | "Âm";
  hourRange?: string;
};

export type BatTu = {
  year: Pillar;
  month: Pillar;
  day: Pillar;
  hour: Pillar;
};

function julianDay(year: number, month: number, day: number): number {
  const a = Math.floor((14 - month) / 12);
  const y = year + 4800 - a;
  const m = month + 12 * a - 3;
  return (
    day +
    Math.floor((153 * m + 2) / 5) +
    365 * y +
    Math.floor(y / 4) -
    Math.floor(y / 100) +
    Math.floor(y / 400) -
    32045
  );
}

function pillarOf(stemIdx: number, branchIdx: number, hourRange?: string): Pillar {
  const stem = STEMS[((stemIdx % 10) + 10) % 10];
  const branch = BRANCHES[((branchIdx % 12) + 12) % 12];
  return {
    stem,
    branch,
    element: STEM_ELEMENT[stem],
    yinYang: STEM_YIN_YANG[stem],
    hourRange,
  };
}

/** Hour branch from 24h hour. Tý spans 23:00 next day boundary. */
function hourBranchFromHour(h: number): number {
  // 23, 0 -> Tý (0); 1,2 -> Sửu (1); 3,4 -> Dần (2); ...
  if (h === 23 || h === 0) return 0;
  return Math.floor((h + 1) / 2) % 12;
}

export function computeBatTu(year: number, month: number, day: number, hour: number): BatTu {
  // Năm: 1924 = Giáp Tý → stem=0 branch=0
  const yStem = (year - 1924) % 10;
  const yBranch = (year - 1924) % 12;

  // Tháng: nguyệt-thủ depends on year-stem.
  // Năm Giáp/Kỷ → tháng Dần khởi từ Bính Dần (stem=2)
  // Năm Ất/Canh → tháng Dần khởi từ Mậu Dần (stem=4)
  // Năm Bính/Tân → tháng Dần khởi từ Canh Dần (stem=6)
  // Năm Đinh/Nhâm → tháng Dần khởi từ Nhâm Dần (stem=8)
  // Năm Mậu/Quý → tháng Dần khởi từ Giáp Dần (stem=0)
  const monthFirstStem: Record<number, number> = {
    0: 2,
    5: 2, // Giáp, Kỷ
    1: 4,
    6: 4, // Ất, Canh
    2: 6,
    7: 6, // Bính, Tân
    3: 8,
    8: 8, // Đinh, Nhâm
    4: 0,
    9: 0, // Mậu, Quý
  };
  const yStemNorm = ((yStem % 10) + 10) % 10;
  // Tháng âm lịch số = month (gần đúng). Tháng 1 = Dần → branchOffset 2.
  const monthBranchIdx = (month + 1) % 12; // tháng 1 → Dần idx 2
  const monthStemBase = monthFirstStem[yStemNorm];
  const monthStemIdx = (monthStemBase + (month - 1)) % 10;

  // Ngày: anchor Julian Day 2415021 (Jan 1, 1900) = Giáp Tuất → stem=0 branch=10
  const jd = julianDay(year, month, day);
  const dayStemIdx = (jd - 2415021 + 0) % 10;
  const dayBranchIdx = (jd - 2415021 + 10) % 12;

  // Giờ: chi từ giờ; can = 2 × (nhật-can mod 5) + chi giờ
  const hourBranchIdx = hourBranchFromHour(hour);
  const dayStemMod = ((dayStemIdx % 10) + 10) % 10;
  const hourStemBase = (2 * (dayStemMod % 5)) % 10;
  const hourStemIdx = (hourStemBase + hourBranchIdx) % 10;

  return {
    year: pillarOf(yStem, yBranch),
    month: pillarOf(monthStemIdx, monthBranchIdx),
    day: pillarOf(dayStemIdx, dayBranchIdx),
    hour: pillarOf(hourStemIdx, hourBranchIdx, BRANCH_HOUR_RANGES[hourBranchIdx][1]),
  };
}

/** Tổng hợp ngũ hành 8 chữ — đếm số can/chi mỗi hành. */
export function fiveElementsCount(b: BatTu): Record<string, number> {
  const all = [b.year, b.month, b.day, b.hour];
  const counts: Record<string, number> = { Mộc: 0, Hỏa: 0, Thổ: 0, Kim: 0, Thuỷ: 0 };
  // Stems
  for (const p of all) counts[p.element] = (counts[p.element] ?? 0) + 1;
  // Branches → element of branch
  const BRANCH_ELEMENT: Record<string, string> = {
    Tý: "Thuỷ",
    Sửu: "Thổ",
    Dần: "Mộc",
    Mão: "Mộc",
    Thìn: "Thổ",
    Tỵ: "Hỏa",
    Ngọ: "Hỏa",
    Mùi: "Thổ",
    Thân: "Kim",
    Dậu: "Kim",
    Tuất: "Thổ",
    Hợi: "Thuỷ",
  };
  for (const p of all) {
    const el = BRANCH_ELEMENT[p.branch];
    counts[el] = (counts[el] ?? 0) + 1;
  }
  return counts;
}

/** Mệnh chính dùng nhật-can. */
export function dayMaster(b: BatTu): { stem: string; element: string; yinYang: "Dương" | "Âm" } {
  return {
    stem: b.day.stem,
    element: b.day.element,
    yinYang: b.day.yinYang,
  };
}

// =============================================================
// Dụng thần — lucky element analysis
// =============================================================

/**
 * Dụng thần (favorable element) — phân tích đơn giản hoá:
 *
 * Day Master + ngũ hành đồng loại (cùng hành như Day Master) tạo nên
 * "tổng tự thân" của lá số:
 *   - Tự thân vượng (>= 4 điểm trên thang 8): cần KHẮC, TIẾT, hoặc HAO
 *     → dụng thần là hành KHẮC Day Master, hành Day Master KHẮC, hoặc
 *       hành Day Master SINH ra (tiết khí)
 *   - Tự thân nhược (< 4 điểm): cần SINH hoặc TỶ KIẾP
 *     → dụng thần là hành SINH Day Master hoặc cùng hành Day Master
 *
 * Đây là cách giản lược — nguyên gốc Bát Tự xét cả khí thế tháng sinh,
 * lệnh, hợp xung. Cách rút gọn này phù hợp tool web tham khảo, không
 * thay thế tư vấn chuyên sâu.
 */

const SINH_CHAIN: Record<string, string> = {
  Mộc: "Hỏa",
  Hỏa: "Thổ",
  Thổ: "Kim",
  Kim: "Thuỷ",
  Thuỷ: "Mộc",
};

const KHAC_CHAIN: Record<string, string> = {
  Mộc: "Thổ",
  Thổ: "Thuỷ",
  Thuỷ: "Hỏa",
  Hỏa: "Kim",
  Kim: "Mộc",
};

const SINH_REVERSE: Record<string, string> = {
  Hỏa: "Mộc",
  Thổ: "Hỏa",
  Kim: "Thổ",
  Thuỷ: "Kim",
  Mộc: "Thuỷ",
};

const KHAC_REVERSE: Record<string, string> = {
  Thổ: "Mộc",
  Thuỷ: "Thổ",
  Hỏa: "Thuỷ",
  Kim: "Hỏa",
  Mộc: "Kim",
};

const ELEMENT_DIRECTION: Record<string, string[]> = {
  Mộc: ["Đông", "Đông Nam"],
  Hỏa: ["Nam"],
  Thổ: ["Đông Bắc", "Tây Nam"],
  Kim: ["Tây", "Tây Bắc"],
  Thuỷ: ["Bắc"],
};

const ELEMENT_COLORS: Record<string, string[]> = {
  Mộc: ["Xanh lá", "Xanh đậm"],
  Hỏa: ["Đỏ", "Hồng", "Tím", "Cam"],
  Thổ: ["Vàng đất", "Nâu", "Be"],
  Kim: ["Trắng", "Bạc", "Vàng kim"],
  Thuỷ: ["Đen", "Xanh navy"],
};

const ELEMENT_NUMBERS: Record<string, number[]> = {
  Mộc: [3, 8],
  Hỏa: [2, 7],
  Thổ: [5, 0],
  Kim: [4, 9],
  Thuỷ: [1, 6],
};

const ELEMENT_CAREERS: Record<string, string[]> = {
  Mộc: ["Giáo dục", "Nông nghiệp", "Y dược", "Môi trường", "Thiết kế bền vững"],
  Hỏa: ["Marketing", "Truyền thông", "F&B", "Giải trí", "Thời trang"],
  Thổ: ["Bất động sản", "Xây dựng", "Hành chính", "Kế toán", "Gốm sứ"],
  Kim: ["Tài chính", "Kỹ thuật chính xác", "Luật", "Kim hoàn", "Lãnh đạo"],
  Thuỷ: ["Truyền thông", "Vận tải", "Du lịch", "Công nghệ", "Nghiên cứu"],
};

export type DungThan = {
  dayMasterElement: string;
  dayMasterYinYang: "Dương" | "Âm";
  selfStrength: "vượng" | "nhược" | "trung hoà";
  selfScore: number; // 0-8 (đếm điểm Day Master + cùng hành)
  totalElements: number; // total count to compute ratios
  needs: string[]; // 1-3 elements that should be added
  avoids: string[]; // 1-2 elements that are too strong
  directions: string[];
  colors: string[];
  numbers: number[];
  careers: string[];
  summary: string;
};

export function computeDungThan(b: BatTu): DungThan {
  const counts = fiveElementsCount(b);
  const total = Object.values(counts).reduce((s, n) => s + n, 0); // typically 8
  const dm = dayMaster(b);
  const dmEl = dm.element;
  const selfScore = counts[dmEl] ?? 0;

  // Determine strength
  let selfStrength: DungThan["selfStrength"] = "trung hoà";
  if (selfScore >= 4) selfStrength = "vượng";
  else if (selfScore <= 2) selfStrength = "nhược";

  let needs: string[] = [];
  let avoids: string[] = [];

  if (selfStrength === "vượng") {
    // Need: KHẮC Day Master, Day Master KHẮC, or Day Master SINH (tiết khí)
    const elemKhacDm = KHAC_REVERSE[dmEl]; // hành khắc Day Master
    const elemDmKhac = KHAC_CHAIN[dmEl]; // hành Day Master khắc
    const elemDmSinh = SINH_CHAIN[dmEl]; // hành Day Master sinh ra (tiết)
    // Pick the 1-2 weakest of these to add
    const candidates = [elemKhacDm, elemDmSinh, elemDmKhac].filter(Boolean);
    candidates.sort((a, b) => (counts[a] ?? 0) - (counts[b] ?? 0));
    needs = candidates.slice(0, 2);
    // Avoid: cùng hành Day Master và hành sinh Day Master (làm vượng thêm)
    avoids = [dmEl, SINH_REVERSE[dmEl]];
  } else if (selfStrength === "nhược") {
    // Need: SINH Day Master or cùng hành (Tỷ Kiếp)
    const elemSinhDm = SINH_REVERSE[dmEl];
    needs = [elemSinhDm, dmEl];
    // Avoid: hành KHẮC Day Master và hành Day Master sinh (tiết khí)
    avoids = [KHAC_REVERSE[dmEl], SINH_CHAIN[dmEl]];
  } else {
    // Trung hoà — bổ sung 1-2 hành thiếu nhất
    const sortedByCount = Object.entries(counts).sort((a, b) => a[1] - b[1]);
    needs = sortedByCount.slice(0, 2).map(([el]) => el);
    avoids = [];
  }

  // Aggregate suggestions across all "needs" elements
  const directions = Array.from(new Set(needs.flatMap((el) => ELEMENT_DIRECTION[el] ?? [])));
  const colors = Array.from(new Set(needs.flatMap((el) => ELEMENT_COLORS[el] ?? [])));
  const numbers = Array.from(new Set(needs.flatMap((el) => ELEMENT_NUMBERS[el] ?? [])));
  const careers = Array.from(new Set(needs.flatMap((el) => ELEMENT_CAREERS[el] ?? []))).slice(0, 6);

  const summary =
    selfStrength === "vượng"
      ? `Nhật chủ ${dmEl} vượng (${selfScore}/${total} điểm). Dụng thần là ${needs.join(", ")} — cần khắc chế hoặc tiết khí để cân bằng. Tránh bổ sung ${avoids.join(", ")} vì sẽ làm Nhật chủ càng vượng.`
      : selfStrength === "nhược"
        ? `Nhật chủ ${dmEl} nhược (${selfScore}/${total} điểm). Dụng thần là ${needs.join(", ")} — cần được sinh phù để mạnh lên. Tránh ${avoids.join(", ")} vì sẽ làm Nhật chủ càng yếu.`
        : `Nhật chủ ${dmEl} trung hoà (${selfScore}/${total} điểm). Bát Tự khá cân bằng — chỉ cần bổ sung ${needs.join(", ")} để hoàn thiện ngũ hành.`;

  return {
    dayMasterElement: dmEl,
    dayMasterYinYang: dm.yinYang,
    selfStrength,
    selfScore,
    totalElements: total,
    needs,
    avoids,
    directions,
    colors,
    numbers,
    careers,
    summary,
  };
}
