import os, datetime, threading, json
import customtkinter as ctk
from tkinter import messagebox
from skyfield.api import Loader
from skyfield import almanac

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

BULAN_HIJRIAH = ["Muharam", "Safar", "Rabiulawal", "Rabiulakhir", "Jumadilawal", "Jumadilakhir", "Rajab", "Syakban", "Ramadan", "Syawal", "Zulkaidah", "Zulhijah"]
hari_nama = ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Ahad"]
bulan_masehi_singkat = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

class Menu30App(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.title("HIJRI_DB Auto-Builder (Modul 30)")
        self.geometry("900x600")
        ctk.set_appearance_mode("Dark")
        
        self.load_obj = Loader(BASE_DIR)
        self.eph = self.load_obj('de421.bsp')
        self.ts = self.load_obj.timescale()
        
        self.setup_ui()

    def get_approx_nm_tt(self, y, m):
        abs_month = (y - 1) * 12 + m
        return 2451550.0 + (abs_month - 17038) * 29.530588853

    def get_new_moons_in_range(self, start_tt_float, end_tt_float):
        t0 = self.ts.tt_jd(start_tt_float)
        t1 = self.ts.tt_jd(end_tt_float)
        t_obj, y_obj = almanac.find_discrete(t0, t1, almanac.moon_phases(self.eph))
        if t_obj is None: return []
        
        if getattr(t_obj, 'shape', ()) == ():
            tt_list, y_list = [float(t_obj.tt)], [int(y_obj)]
        else:
            tt_list, y_list = t_obj.tt.tolist(), y_obj.tolist()
            
        new_moons_tt = []
        for i in range(len(y_list)):
            if y_list[i] == 0: new_moons_tt.append(tt_list[i])
        return new_moons_tt

    def calculate_khgt_1st_of_month(self, nm_tt_float):
        t_nm = self.ts.tt_jd(nm_tt_float)
        y, m, d, h, mi, s = t_nm.utc
        t_midnight = self.ts.utc(y, m, d)
        
        # Logika PKG KHGT Murni (Sesuai batas Fajar Gisborne = Jam 15 UTC)
        if h < 15: return t_midnight.tt + 1.0
        else: return t_midnight.tt + 2.0

    def setup_ui(self):
        self.sidebar = ctk.CTkFrame(self, width=250)
        self.sidebar.pack(side="left", fill="y", padx=10, pady=10)
        
        ctk.CTkLabel(self.sidebar, text="DATABASE BUILDER\n(KHGT ENGINE)", font=("Segoe UI", 16, "bold"), text_color="#FFD54F").pack(pady=20)
        
        ctk.CTkLabel(self.sidebar, text="Tahun Awal (H):").pack()
        self.entry_start = ctk.CTkEntry(self.sidebar); self.entry_start.insert(0, "1447"); self.entry_start.pack(pady=5)
        
        ctk.CTkLabel(self.sidebar, text="Tahun Akhir (H):").pack()
        self.entry_end = ctk.CTkEntry(self.sidebar); self.entry_end.insert(0, "1496"); self.entry_end.pack(pady=5)
        
        self.btn_hitung = ctk.CTkButton(self.sidebar, text="⚙️ GENERATE DB JSON", fg_color="#F57C00", hover_color="#E65100", command=self.mulai_build, height=45)
        self.btn_hitung.pack(pady=30, fill="x", padx=15)
        
        self.lbl_status = ctk.CTkLabel(self.sidebar, text="Sistem Siap", text_color="#00E676")
        self.lbl_status.pack()

        self.textbox = ctk.CTkTextbox(self, font=("Consolas", 14), wrap="none")
        self.textbox.pack(side="right", fill="both", expand=True, padx=10, pady=10)
        self.textbox.insert("1.0", "Klik tombol di samping untuk menghasilkan dataset Kalender KHGT selama 50 tahun ke depan.\n\nSistem akan merekonstruksi ulang penanggalan berbasis Ephemeris NASA, lalu mengekspornya sebagai 'db_hijriah.json'.")
        self.textbox.configure(state="disabled")

    def mulai_build(self):
        threading.Thread(target=self._build_hijri_db_thread, daemon=True).start()

    def _build_hijri_db_thread(self):
        try:
            start_year = int(self.entry_start.get())
            end_year = int(self.entry_end.get())
        except ValueError:
            self.after(0, lambda: messagebox.showerror("Error", "Tahun harus berupa angka."))
            return

        self.after(0, lambda: self.lbl_status.configure(text=f"Membangun DB {start_year}-{end_year}...", text_color="#00E5FF"))
        self.after(0, lambda: self.textbox.configure(state="normal"))
        self.after(0, lambda: self.textbox.delete("1.0", "end"))
        self.after(0, lambda: self.textbox.insert("end", f"Memulai iterasi mesin KHGT dari tahun {start_year} H hingga {end_year} H...\nProses ini memerlukan waktu pemrosesan CPU, mohon tunggu...\n\n"))
        self.after(0, lambda: self.btn_hitung.configure(state="disabled"))

        new_db = {}
        try:
            for y_h in range(start_year, end_year + 1):
                year_data = []
                for m_h in range(1, 13):
                    approx_tt_curr = self.get_approx_nm_tt(y_h, m_h)
                    nm_list_curr = self.get_new_moons_in_range(approx_tt_curr - 5.0, approx_tt_curr + 5.0)
                    if not nm_list_curr: raise ValueError(f"Fase Bulan Baru tidak ditemukan untuk {y_h}-{m_h}")
                    
                    nm_curr = nm_list_curr[0]
                    start_tt_curr = self.calculate_khgt_1st_of_month(nm_curr)

                    next_m, next_y = m_h + 1, y_h
                    if next_m > 12: next_m, next_y = 1, y_h + 1

                    approx_tt_next = self.get_approx_nm_tt(next_y, next_m)
                    nm_list_next = self.get_new_moons_in_range(approx_tt_next - 5.0, approx_tt_next + 5.0)
                    nm_next = nm_list_next[0]
                    start_tt_next = self.calculate_khgt_1st_of_month(nm_next)

                    jumlah_hari = int(round(start_tt_next - start_tt_curr))

                    t_obj = self.ts.tt_jd(start_tt_curr)
                    gy, gm, gd, _, _, _ = t_obj.utc
                    nama_h = hari_nama[int(t_obj.whole % 7)]
                    tgl_str = f"{int(gd):02d}-{bulan_masehi_singkat[int(gm)-1]}-{int(gy)}"

                    year_data.append([BULAN_HIJRIAH[m_h-1], nama_h, tgl_str, jumlah_hari])

                new_db[y_h] = year_data
                self.after(0, lambda yr=y_h: self.textbox.insert("end", f"✓ Tahun {yr} H berhasil diproses...\n"))
                self.after(0, lambda: self.textbox.see("end"))

            db_path = os.path.join(BASE_DIR, "db_hijriah.json")
            with open(db_path, "w", encoding="utf-8") as f:
                json.dump(new_db, f, indent=4, ensure_ascii=False)

            self.after(0, lambda: self.textbox.insert("end", f"\n[+] SUKSES! Database JSON KHGT berhasil dibangun dan disimpan ke:\n{db_path}\nData ini dapat dibaca oleh Modul Kalender (Menu 26 & 27)."))
            self.after(0, lambda: self.lbl_status.configure(text="Selesai", text_color="#00E676"))

        except Exception as e:
            self.after(0, lambda err=str(e): self.textbox.insert("end", f"\nERROR: {err}"))
            self.after(0, lambda: self.lbl_status.configure(text="Auto-Builder Gagal", text_color="#FF1744"))
        finally:
            self.after(0, lambda: self.btn_hitung.configure(state="normal"))
            self.after(0, lambda: self.textbox.configure(state="disabled"))

if __name__ == "__main__":
    app = Menu30App()
    app.mainloop()