import customtkinter as ctk
import math
from datetime import datetime

# Set tema dan warna
ctk.set_appearance_mode("light")
ctk.set_default_color_theme("blue")

class FalakCalculator(ctk.CTk):
    def __init__(self):
        super().__init__()

        self.title("Kalkulator Falak Komprehensif (50 Parameter)")
        self.geometry("1200x900")

        # Konstan Astronomi
        self.D2R = math.pi / 180
        self.R2D = 180 / math.pi

        self.setup_ui()

    def setup_ui(self):
        # Frame Utama dengan Scroll
        self.main_container = ctk.CTkScrollableFrame(self, fg_color="#f0f2f5")
        self.main_container.pack(fill="both", expand=True, padx=20, pady=20)

        # Title
        title_label = ctk.CTkLabel(self.main_container, text="Kalkulator Falak 50 Parameter", 
                                   font=("Segoe UI", 28, "bold"), text_color="#1a73e8")
        title_label.pack(pady=(10, 30))

        # Grid Input
        input_frame = ctk.CTkFrame(self.main_container, fg_color="#f8f9fa", corner_radius=15)
        input_frame.pack(fill="x", padx=10, pady=10)
        
        for i in range(5): input_frame.grid_columnconfigure(i, weight=1)

        self.inputs = {}
        fields = [
            ("Lintang (Lat)", "lat", "-6.9667"),
            ("Bujur (Lon)", "lon", "110.4167"),
            ("Tinggi (m)", "alt", "10"),
            ("Zona Waktu", "tz", "7"),
            ("Tanggal (YYYY-MM-DD)", "date", datetime.now().strftime("%Y-%m-%d"))
        ]

        for i, (label, key, default) in enumerate(fields):
            container = ctk.CTkFrame(input_frame, fg_color="transparent")
            container.grid(row=0, column=i, padx=10, pady=15, sticky="nsew")
            
            ctk.CTkLabel(container, text=label, font=("Segoe UI", 12, "bold")).pack(anchor="w")
            entry = ctk.CTkEntry(container, placeholder_text=default)
            entry.insert(0, default)
            entry.pack(fill="x", pady=5)
            self.inputs[key] = entry

        # Tombol Hitung
        self.btn_calc = ctk.CTkButton(self.main_container, text="HITUNG SELURUH PARAMETER", 
                                      height=50, font=("Segoe UI", 16, "bold"),
                                      command=self.hitung_utama)
        self.btn_calc.pack(fill="x", padx=10, pady=20)

        # Area Output (Grid)
        self.output_container = ctk.CTkFrame(self.main_container, fg_color="transparent")
        self.output_container.pack(fill="both", expand=True)

    def rev(self, angle):
        return angle - 360 * math.floor(angle / 360)

    def format_jam(self, decimal):
        if decimal is None: return "--:--:--"
        decimal = self.rev(decimal * 15) / 15 # Normalisasi ke 24 jam
        h = int(decimal)
        m = int((decimal - h) * 60)
        s = int(((decimal - h) * 60 - m) * 60)
        return f"{h:02d}:{m:02d}:{s:02d}"

    def get_h(self, h, d, p):
        val = (math.sin(h * self.D2R) - math.sin(p * self.D2R) * math.sin(d * self.D2R)) / (math.cos(p * self.D2R) * math.cos(d * self.D2R))
        if val > 1 or val < -1: return None
        return math.acos(val) * self.R2D / 15

    def hitung_utama(self):
        # Bersihkan output
        for widget in self.output_container.winfo_children():
            widget.destroy()

        try:
            lat = float(self.inputs['lat'].get())
            lon = float(self.inputs['lon'].get())
            alt = float(self.inputs['alt'].get())
            tz = float(self.inputs['tz'].get())
            d_str = self.inputs['date'].get()
            d_in = datetime.strptime(d_str, "%Y-%m-%d")

            Y, M, D = d_in.year, d_in.month, d_in.day
            if M <= 2: Y -= 1; M += 12

            # 1. WAKTU DASAR
            A = math.floor(Y / 100)
            B = 2 - A + math.floor(A / 4)
            JD = math.floor(365.25 * (Y + 4716)) + math.floor(30.6001 * (M + 1)) + D + B - 1524.5
            T = (JD - 2451545.0) / 36525
            gmst = self.rev(280.46061837 + 360.98564736629 * (JD - 2451545.0))

            # 2. PARAMETER MATAHARI
            L0 = self.rev(280.46646 + 36000.76983 * T)
            Msun = self.rev(357.52911 + 35999.05029 * T)
            e = 0.016708634 - 0.000042037 * T
            C = (1.914602 - 0.004817 * T) * math.sin(Msun * self.D2R) + (0.019993 - 0.000101 * T) * math.sin(2 * Msun * self.D2R)
            sunTrueLong = L0 + C
            eps0 = 23.439291 - 0.0130041 * T
            delta = math.asin(math.sin(eps0 * self.D2R) * math.sin(sunTrueLong * self.D2R)) * self.R2D
            RA = math.atan2(math.cos(eps0 * self.D2R) * math.sin(sunTrueLong * self.D2R), math.cos(sunTrueLong * self.D2R)) * self.R2D / 15
            EoT = (L0 / 15 - RA) * 60 
            R_sun = (1.00014 - 0.01671 * math.cos(Msun * self.D2R) - 0.00014 * math.cos(2 * Msun * self.D2R))
            SD_sun = 0.2666 / R_sun

            # 3. PARAMETER BULAN
            Lp = self.rev(218.316 + 481267.881 * T)
            Dmoon = self.rev(297.85 + 445267.11 * T)
            Mmoon = self.rev(134.96 + 477198.86 * T)
            Fmoon = self.rev(93.27 + 483202.01 * T)
            Node = self.rev(125.04 - 1934.136 * T)
            HP_moon = 0.9507 / R_sun # Sederhana

            # 4. KOREKSI UFUK
            Dip = 1.76 / 60 * math.sqrt(alt)
            Refr = 34.5 / 60
            h_maghrib = -(SD_sun + Refr + Dip)

            # 5. WAKTU SALAT
            Transit = (12 + tz - lon / 15 - EoT / 60)
            H_subuh = self.get_h(-20.0, delta, lat)
            H_isya = self.get_h(-18.0, delta, lat)
            H_maghrib = self.get_h(h_maghrib, delta, lat)
            H_syuruq = self.get_h(h_maghrib, delta, lat) # Menggunakan h yang sama dengan maghrib (terbit)
            H_ashar = self.get_h(self.R2D * math.atan(1 + math.tan(abs(lat - delta) * self.D2R)), delta, lat)

            # 6. KIBLAT
            latK, lonK = 21.4225, 39.8262
            dL = (lon - lonK) * self.D2R
            Q = math.atan2(math.sin(dL), math.cos(lat * self.D2R) * math.tan(latK * self.D2R) - math.sin(lat * self.D2R) * math.cos(dL)) * self.R2D
            AzKiblat = self.rev(360 - Q)
            distK = math.acos(math.sin(latK*self.D2R)*math.sin(lat*self.D2R) + math.cos(latK*self.D2R)*math.cos(lat*self.D2R)*math.cos(dL)) * 6371

            # MAPPING SEMUA 50 PARAMETER (SESUAI JS)
            display_data = [
                ("DATA WAKTU & KALENDER", "S"),
                ("Julian Day", f"{JD:.4f}"), ("Julian Century (T)", f"{T:.8f}"), ("GMST (Greenwich)", f"{gmst:.4f}°"),
                ("Equation of Time", f"{EoT:.2f} m"), ("Delta T (Est)", "69.0 s"), ("Tahun Astronomi", f"{Y}"),
                
                ("PARAMETER MATAHARI", "S"),
                ("Bujur Rata (L0)", f"{L0:.4f}°"), ("Anomali Rata (M)", f"{Msun:.4f}°"), ("Eksentrisitas (e)", f"{e:.7f}"),
                ("Persamaan Pusat (C)", f"{C:.4f}°"), ("Bujur Hakiki (Θ)", f"{sunTrueLong:.4f}°"), ("Obliquity (ε)", f"{eps0:.4f}°"),
                ("Deklinasi (δ)", f"{delta:.4f}°"), ("Right Ascension (α)", f"{RA:.4f} j"), ("Jarak Bumi-Sun", f"{R_sun:.6f} AU"),
                ("Semidiameter Sun", f"{SD_sun:.4f}°"), ("Nutasi Bujur", "Pending"), ("Paralaks Sun", "0.0024°"),

                ("PARAMETER BULAN", "S"),
                ("Bujur Rata Bulan", f"{Lp:.4f}°"), ("Elongasi (D)", f"{Dmoon:.4f}°"), ("Anomali Bulan (M')", f"{Mmoon:.4f}°"),
                ("Argumen Lintang (F)", f"{Fmoon:.4f}°"), ("Simpul Node (Ω)", f"{Node:.4f}°"), ("HP Bulan", f"{HP_moon:.4f}°"),
                ("Fase Bulan", "Coming Soon"), ("Bujur Ecl. Bulan", "Pending"), ("Lintang Ecl. Bulan", "Pending"),

                ("KOREKSI UFUK & LOKAL", "S"),
                ("Kerendahan Ufuk (Dip)", f"{Dip:.4f}°"), ("Refraksi Atmosfer", f"{Refr:.4f}°"), ("Tinggi Maghrib (h)", f"{h_maghrib:.4f}°"),
                ("Tinggi Subuh", "-20.0000°"), ("Tinggi Isya", "-18.0000°"), ("Sudut Syuruq", f"{h_maghrib:.4f}°"),

                ("WAKTU SALAT (ISTIWA)", "S"),
                ("Istiwa / Zuhur", self.format_jam(Transit)),
                ("Subuh (-20°)", self.format_jam(Transit - H_subuh if H_subuh else 0)),
                ("Syuruq (Terbit)", self.format_jam(Transit - H_syuruq if H_syuruq else 0)),
                ("Ashar (Syafi'i)", self.format_jam(Transit + H_ashar if H_ashar else 0)),
                ("Maghrib", self.format_jam(Transit + H_maghrib if H_maghrib else 0)),
                ("Isya (-18°)", self.format_jam(Transit + H_isya if H_isya else 0)),

                ("ARAH KIBLAT", "S"),
                ("Azimut Kiblat", f"{AzKiblat:.2f}° U-T"), ("Jarak ke Ka'bah", f"{distK:.2f} km"),
                ("Lintang Ka'bah", "21.4225° N"), ("Bujur Ka'bah", "39.8262° E"), ("Sudut Q", f"{Q:.4f}°")
            ]

            # Render Cards (4 Kolom agar muat banyak)
            row, col = 0, 0
            for item in display_data:
                if item[1] == "S":
                    row += 1
                    section = ctk.CTkLabel(self.output_container, text=item[0], font=("Segoe UI", 14, "bold"), 
                                           fg_color="#e8f0fe", text_color="#1967d2", corner_radius=5, height=35)
                    section.grid(row=row, column=0, columnspan=4, sticky="ew", pady=(20, 10), padx=10)
                    row += 1
                    col = 0
                else:
                    card = ctk.CTkFrame(self.output_container, fg_color="white", border_width=1, border_color="#e0e0e0")
                    card.grid(row=row, column=col, padx=8, pady=5, sticky="nsew")
                    
                    ctk.CTkLabel(card, text=item[0].upper(), font=("Segoe UI", 10, "bold"), text_color="#1a73e8").pack(pady=(8,0), padx=10)
                    ctk.CTkLabel(card, text=item[1], font=("Courier New", 14, "bold"), text_color="#333").pack(pady=(2,8), padx=10)
                    
                    col += 1
                    if col > 3: # 4 Kolom
                        col = 0
                        row += 1

        except Exception as e:
            from tkinter import messagebox
            messagebox.showerror("Error", f"Terjadi kesalahan input: {str(e)}")

if __name__ == "__main__":
    app = FalakCalculator()
    app.mainloop()