import customtkinter as ctk
from google import genai
import threading
import json
import os
import webbrowser
import urllib.parse
from datetime import datetime
from tkinter import filedialog, messagebox

# ==========================================
# KONFIGURASI API GEMINI (SDK BARU)
# ==========================================
API_KEY = "AIzaSyBr8JNYr6Qf8MQaRYs7bgz0HQVnvK4eDBg123"
client = genai.Client(api_key=API_KEY)

class WinAIAssistant(ctk.CTk):
    """
    Kelas utama untuk Aplikasi Desktop AI Asisten.
    Menggunakan CustomTkinter untuk UI modern bergaya Windows 11.
    """
    def __init__(self):
        super().__init__()

        # Konfigurasi Window Utama
        self.title("AI Desktop Assistant")
        self.geometry("1200x800")
        self.after(0, lambda: self.state('zoomed'))
        
        ctk.set_appearance_mode("System")
        ctk.set_default_color_theme("blue")

        # Variabel State
        self.history_file = "data.json"
        self.chat_history = self.load_history()
        self.current_response_text = ""

        self.setup_ui()
        self.populate_sidebar_history()

    def setup_ui(self):
        """Membangun grid dan elemen antarmuka pengguna (UI)."""
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=1)

        # ==================== SIDEBAR ====================
        self.sidebar_frame = ctk.CTkFrame(self, width=250, corner_radius=0)
        self.sidebar_frame.grid(row=0, column=0, sticky="nsew")
        self.sidebar_frame.grid_rowconfigure(2, weight=1)

        self.logo_label = ctk.CTkLabel(self.sidebar_frame, text="AI Assistant", font=("Segoe UI", 24, "bold"))
        self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10))

        self.new_chat_btn = ctk.CTkButton(self.sidebar_frame, text="+ Percakapan Baru", command=self.clear_chat)
        self.new_chat_btn.grid(row=1, column=0, padx=20, pady=10)

        # Area Riwayat Percakapan (Scrollable)
        self.history_scroll = ctk.CTkScrollableFrame(self.sidebar_frame, label_text="Riwayat Percakapan")
        self.history_scroll.grid(row=2, column=0, sticky="nsew", padx=10, pady=10)

        # Pengaturan Tema
        self.appearance_mode_label = ctk.CTkLabel(self.sidebar_frame, text="Tema Tampilan:", anchor="w")
        self.appearance_mode_label.grid(row=3, column=0, padx=20, pady=(10, 0))
        self.appearance_mode_optionemenu = ctk.CTkOptionMenu(self.sidebar_frame, values=["Light", "Dark", "System"],
                                                             command=self.change_appearance_mode_event)
        self.appearance_mode_optionemenu.grid(row=4, column=0, padx=20, pady=(10, 20))

        # ==================== MAIN CONTENT ====================
        self.main_frame = ctk.CTkFrame(self, corner_radius=0, fg_color="transparent")
        self.main_frame.grid(row=0, column=1, sticky="nsew")
        self.main_frame.grid_rowconfigure(0, weight=1)
        self.main_frame.grid_columnconfigure(0, weight=1)

        # Area Chat Display
        self.chat_display = ctk.CTkTextbox(self.main_frame, wrap="word", font=("Segoe UI", 15))
        self.chat_display.grid(row=0, column=0, padx=20, pady=(20, 10), sticky="nsew")
        self.chat_display.configure(state="disabled")
        
        # FIX: Gunakan _textbox (widget internal tkinter asli) untuk melewati proteksi error CustomTkinter
        self.chat_display._textbox.tag_config("h1", font=("Segoe UI", 22, "bold"))
        self.chat_display._textbox.tag_config("h2", font=("Segoe UI", 20, "bold"))
        self.chat_display._textbox.tag_config("h3", font=("Segoe UI", 18, "bold"))
        self.chat_display._textbox.tag_config("bold", font=("Segoe UI", 15, "bold"))
        self.chat_display._textbox.tag_config("normal", font=("Segoe UI", 15))
        self.chat_display._textbox.tag_config("user", font=("Segoe UI", 16, "bold"), foreground="#1f6aa5")
        self.chat_display._textbox.tag_config("error", font=("Segoe UI", 15, "italic"), foreground="red")

        # Action Buttons Area
        self.action_frame = ctk.CTkFrame(self.main_frame, fg_color="transparent")
        self.action_frame.grid(row=1, column=0, padx=20, pady=0, sticky="e")
        
        self.btn_copy = ctk.CTkButton(self.action_frame, text="Salin", width=80, command=self.copy_response)
        self.btn_copy.pack(side="left", padx=5)
        self.btn_save = ctk.CTkButton(self.action_frame, text="Simpan", width=80, command=self.save_to_text_file)
        self.btn_save.pack(side="left", padx=5)
        self.btn_share = ctk.CTkButton(self.action_frame, text="Share WA", width=80, fg_color="#25D366", hover_color="#128C7E", command=self.share_to_wa)
        self.btn_share.pack(side="left", padx=5)

        # Area Input Prompt
        self.input_frame = ctk.CTkFrame(self.main_frame, fg_color="transparent")
        self.input_frame.grid(row=2, column=0, padx=20, pady=(10, 20), sticky="ew")
        self.input_frame.grid_columnconfigure(0, weight=1)

        self.input_entry = ctk.CTkEntry(self.input_frame, placeholder_text="Ketik pesan Anda di sini...", font=("Segoe UI", 15), height=50)
        self.input_entry.grid(row=0, column=0, padx=(0, 10), sticky="ew")
        self.input_entry.bind("<Return>", lambda event: self.handle_send())

        self.send_btn = ctk.CTkButton(self.input_frame, text="Kirim", font=("Segoe UI", 15, "bold"), width=100, height=50, command=self.handle_send)
        self.send_btn.grid(row=0, column=1)

    def change_appearance_mode_event(self, new_appearance_mode: str):
        ctk.set_appearance_mode(new_appearance_mode)

    def load_history(self):
        if os.path.exists(self.history_file):
            try:
                with open(self.history_file, "r", encoding="utf-8") as f:
                    return json.load(f)
            except Exception:
                return []
        return []

    def save_history(self, question, answer):
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        entry = {
            "timeline": timestamp,
            "pertanyaan": question,
            "jawaban": answer
        }
        self.chat_history.append(entry)
        with open(self.history_file, "w", encoding="utf-8") as f:
            json.dump(self.chat_history, f, indent=4)
        self.populate_sidebar_history()

    def populate_sidebar_history(self):
        for widget in self.history_scroll.winfo_children():
            widget.destroy()

        for item in reversed(self.chat_history):
            q_text = item["pertanyaan"]
            display_text = q_text[:30] + "..." if len(q_text) > 30 else q_text
            btn = ctk.CTkButton(
                self.history_scroll, 
                text=display_text, 
                anchor="w", 
                fg_color="transparent", 
                text_color=("gray10", "gray90"),
                hover_color=("gray70", "gray30"),
                command=lambda q=item["pertanyaan"], a=item["jawaban"]: self.load_past_chat(q, a)
            )
            btn.pack(fill="x", pady=2)

    def load_past_chat(self, question, answer):
        self.clear_chat()
        self.current_response_text = answer
        self.display_message(f"Anda: {question}", "user")
        self.display_message("\nAI: ", "bold")
        self.parse_and_display_markdown(answer)

    def clear_chat(self):
        self.chat_display.configure(state="normal")
        self.chat_display.delete("1.0", "end")
        self.chat_display.configure(state="disabled")
        self.current_response_text = ""

    def display_message(self, text, tag="normal"):
        self.chat_display.configure(state="normal")
        self.chat_display.insert("end", text + "\n", tag)
        self.chat_display.configure(state="disabled")
        self.chat_display.see("end")

    def parse_and_display_markdown(self, text):
        self.chat_display.configure(state="normal")
        lines = text.split('\n')
        
        for line in lines:
            stripped = line.strip()
            if stripped.startswith('### '):
                self.chat_display.insert("end", stripped[4:] + "\n", "h3")
            elif stripped.startswith('## '):
                self.chat_display.insert("end", stripped[3:] + "\n", "h2")
            elif stripped.startswith('# '):
                self.chat_display.insert("end", stripped[2:] + "\n", "h1")
            elif '**' in line:
                parts = line.split('**')
                for i, part in enumerate(parts):
                    if i % 2 == 1: 
                        self.chat_display.insert("end", part, "bold")
                    else:
                        self.chat_display.insert("end", part, "normal")
                self.chat_display.insert("end", "\n")
            elif stripped.startswith('* '):
                self.chat_display.insert("end", "• " + stripped[2:] + "\n", "normal")
            else:
                self.chat_display.insert("end", line + "\n", "normal")
                
        self.chat_display.insert("end", "\n")
        self.chat_display.configure(state="disabled")
        self.chat_display.see("end")

    def handle_send(self):
        prompt = self.input_entry.get().strip()
        if not prompt:
            return

        self.input_entry.delete(0, "end")
        self.display_message(f"Anda: {prompt}\n", "user")
        self.display_message("AI sedang berpikir...", "normal") 
        
        threading.Thread(target=self.fetch_ai_response, args=(prompt,), daemon=True).start()

    def fetch_ai_response(self, prompt):
        try:
            # FIX: Menggunakan SDK Google GenAI yang baru
            response = client.models.generate_content(
                model='gemini-2.5-flash',
                contents=prompt,
            )
            answer = response.text
            self.current_response_text = answer
            
            self.chat_display.configure(state="normal")
            content = self.chat_display.get("1.0", "end-1c")
            clean_content = content.replace("AI sedang berpikir...\n", "")
            self.chat_display.delete("1.0", "end")
            self.chat_display.insert("1.0", clean_content)
            self.chat_display.configure(state="disabled")

            self.display_message("AI: ", "bold")
            self.parse_and_display_markdown(answer)
            self.save_history(prompt, answer)

        except Exception as e:
            self.chat_display.configure(state="normal")
            content = self.chat_display.get("1.0", "end-1c")
            clean_content = content.replace("AI sedang berpikir...\n", "")
            self.chat_display.delete("1.0", "end")
            self.chat_display.insert("1.0", clean_content)
            self.chat_display.configure(state="disabled")
            
            error_msg = f"⚠️ Terjadi Kesalahan Koneksi/API: {str(e)}"
            self.display_message(error_msg, "error")

    def copy_response(self):
        if self.current_response_text:
            self.clipboard_clear()
            self.clipboard_append(self.current_response_text)
            self.update() 

    def save_to_text_file(self):
        if not self.current_response_text:
            return
        
        file_path = filedialog.asksaveasfilename(
            defaultextension=".txt",
            filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
            title="Simpan Respons AI"
        )
        if file_path:
            with open(file_path, "w", encoding="utf-8") as file:
                file.write(self.current_response_text)

    def share_to_wa(self):
        if not self.current_response_text:
            return
        encoded_text = urllib.parse.quote(self.current_response_text)
        wa_url = f"https://wa.me/?text={encoded_text}"
        webbrowser.open(wa_url)

if __name__ == "__main__":
    app = WinAIAssistant()
    app.mainloop()