import customtkinter
import tkinter as tk
from tkinter import filedialog, messagebox
import os
import sys
import threading
import time
import converter
import webbrowser
import downloader
import utils
import config

class VideoConverterGUI:
    def __init__(self, master):
        self.master = master
        master.title("Video Converter")
        # Set a default size to prevent the narrow window
        # You can change the "widthxheight" and add "+x+y" for position.
        master.geometry("600x750+100+100")

        # --- Set Dark Mode by Default ---
        customtkinter.set_appearance_mode("Dark")  # Modes: "System", "Dark", "Light"
        customtkinter.set_default_color_theme(os.path.join(os.path.dirname(__file__), "custom_theme_dark.json"))

        # --- Footer Frame ---
        self.footer_frame = customtkinter.CTkFrame(master, fg_color="transparent")
        self.footer_frame.pack(side="bottom", fill="x", padx=10, pady=(5, 10))

        self.nickname_label = customtkinter.CTkLabel(self.footer_frame, text="by ramforth")
        self.nickname_label.pack(side="left", padx=(10, 0))

        self.gitea_link = customtkinter.CTkLabel(self.footer_frame, text="https://gitea.ramforth.net/ramforth", text_color="#4077d1", cursor="hand2")
        self.gitea_link.pack(side="right", padx=(0, 10))
        self.gitea_link.bind("<Button-1>", lambda e: self.open_link("https://gitea.ramforth.net/ramforth"))
        # Add underline font
        underline_font = customtkinter.CTkFont(family="sans-serif", size=12, underline=True)
        self.gitea_link.configure(font=underline_font)

        # --- Pack bottom elements first ---
        # This makes them stick to the bottom
        self.status_var = customtkinter.StringVar(value="Ready") # Give it a default value
        self.status_label = customtkinter.CTkLabel(master, textvariable=self.status_var)
        # Add padding (x, y)
        self.status_label.pack(side="bottom", fill="x", padx=10, pady=(5, 0))

        self.progress = customtkinter.CTkProgressBar(master, orientation="horizontal")
        self.progress.pack(side="bottom", fill="x", padx=10, pady=(0, 10))
        self.progress.set(0) # Default to 0

        # --- Mode Switch ---
        self.mode_switch = customtkinter.CTkSwitch(master, text="Dark Mode", command=self.toggle_mode)
        # anchor="w" (west) aligns it to the left
        self.mode_switch.pack(pady=10, padx=20, anchor="w")
        self.mode_switch.select() # Start in the "on" (Dark) state
        self.toggle_mode() # Ensure initial mode is set based on switch state

        # --- Main Widgets ---
        self.label = customtkinter.CTkLabel(master, text="Select video file or enter URL:", fg_color="transparent")
        self.label.pack(pady=(10, 5)) # (top_padding, bottom_padding)

        # Use a fg_color to make the label background visible
        self.filepath_label = customtkinter.CTkLabel(master, text="No file selected", fg_color=("gray75", "gray25"))
        self.filepath_label.pack(pady=5, padx=20, fill="x")

        self.browse_button = customtkinter.CTkButton(master, text="Browse", command=self.browse_file)
        self.browse_button.pack(pady=5)

        self.url_label = customtkinter.CTkLabel(master, text="URL:")
        self.url_label.pack(pady=(15, 5)) # Add extra padding on top to create a group

        # Removed width=50, will use fill="x" in pack() instead
        self.url_entry = customtkinter.CTkEntry(master, placeholder_text="https://...")
        self.url_entry.pack(pady=5, padx=20, fill="x")

        self.quality_label = customtkinter.CTkLabel(master, text="Quality:", fg_color="transparent")
        self.quality_label.pack(pady=(15, 5))

        self.quality_var = customtkinter.StringVar(master, value="medium")
        self.quality_menu = customtkinter.CTkOptionMenu(master, variable=self.quality_var, values=["low", "medium", "high", "archive"])
        self.quality_menu.pack(pady=5)

        self.cookies_label = customtkinter.CTkLabel(master, text="Cookies from Browser:", fg_color="transparent")
        self.cookies_label.pack(pady=(15, 5))

        self.cookies_var = customtkinter.StringVar(master, value="none")
        self.cookies_menu = customtkinter.CTkOptionMenu(master, variable=self.cookies_var, values=["none", "brave", "chrome", "chromium", "edge", "firefox", "opera", "safari", "vivaldi", "whale"])
        self.cookies_menu.pack(pady=5)

        self.output_dir_label = customtkinter.CTkLabel(master, text="Output Directory:", fg_color="transparent")
        self.output_dir_label.pack(pady=(15, 5))

        self.output_dir_button = customtkinter.CTkButton(master, text="Select Directory", command=self.select_output_dir)
        self.output_dir_button.pack(pady=5)

        self.output_dir_path_label = customtkinter.CTkLabel(master, text="No directory selected", fg_color=("gray75", "gray25"))
        self.output_dir_path_label.pack(pady=5, padx=20, fill="x")

        self.convert_button = customtkinter.CTkButton(master, text="Convert", command=self.convert)
        self.convert_button.pack(pady=(20, 5)) # Extra top padding

        self.cancel_button = customtkinter.CTkButton(master, text="Cancel", command=self.cancel_conversion, state="disabled")
        self.cancel_button.pack(pady=5)

    def open_link(self, url):
        """Opens the given URL in a web browser."""
        webbrowser.open_new(url)

    def toggle_mode(self):
        # Check if the switch is on (1) or off (0)
        if self.mode_switch.get() == 1:
            customtkinter.set_appearance_mode("Dark")
            customtkinter.set_default_color_theme(os.path.join(os.path.dirname(__file__), "custom_theme_dark.json"))
        else:
            customtkinter.set_appearance_mode("Light")
            customtkinter.set_default_color_theme(os.path.join(os.path.dirname(__file__), "custom_theme_light.json"))

    def browse_file(self):
        filepath = filedialog.askopenfilename()
        if filepath:
            # --- FIX: Use .configure() ---
            self.filepath_label.configure(text=filepath)

    def select_output_dir(self):
        output_dir = filedialog.askdirectory()
        if output_dir:
            # --- FIX: Use .configure() ---
            self.output_dir_path_label.configure(text=output_dir)

    def convert(self):
        input_path = self.filepath_label.cget("text")
        url = self.url_entry.get()
        output_dir = self.output_dir_path_label.cget("text")
        quality = self.quality_var.get()

        # Clear file path if URL is being used
        if url:
            input_path = ""
            self.filepath_label.configure(text="Using URL")
        elif input_path == "No file selected":
             input_path = "" # Ensure it's empty

        if not (input_path or url):
            messagebox.showerror("Error", "Please select a file or enter a URL.")
            return
            
        if output_dir == "No directory selected":
            messagebox.showerror("Error", "Please select an output directory.")
            return

        # --- FIX: Use .configure() and string states ---
        self.convert_button.configure(state="disabled")
        self.cancel_button.configure(state="normal")
        self.status_var.set("Starting...")

        self.conversion_thread = threading.Thread(
            target=self._run_conversion,
            args=(input_path, url, output_dir, quality, self.cookies_var.get()),
            daemon=True
        )
        self.conversion_thread.start()

    def _run_conversion(self, input_path, url, output_dir, quality, cookies_from_browser):
        try:
            if url:
                self.status_var.set("Downloading video...")
                # --- FIX: Use .configure() ---
                self.progress.configure(mode='indeterminate')
                self.progress.start()
                input_path = downloader.download_video(url, output_dir, cookies_from_browser)
                self.progress.stop()
                # --- FIX: Use .configure() ---
                self.progress.configure(mode='determinate')
                if not input_path:
                    raise Exception("Download failed.")

            self.status_var.set("Converting video...")
            duration = utils.get_video_duration(input_path)
            
            if not duration:
                # If we can't get the duration, use indeterminate mode
                self.progress.configure(mode='indeterminate')
                self.progress.start()
            else:
                # --- FIX: Set mode to determinate and clear value ---
                self.progress.configure(mode='determinate')
                self.progress.set(0)

            # --- FIX: Pass duration to the progress updater ---
            self.progress_thread = threading.Thread(target=self._update_progress, args=(duration,), daemon=True)
            self.progress_thread.start()

            success = converter.convert_video(input_path, output_dir, quality)

            if success:
                self.status_var.set("Conversion successful!")
                self.progress.set(1) # Fill the bar on success
                messagebox.showinfo("Success", "Conversion completed successfully!")
            else:
                raise Exception("Conversion failed. Check logs for details.")

        except Exception as e:
            self.status_var.set(f"Error: {e}")
            try:
                with open(config.FFMPEG_LOG_FILE_PATH, "r") as f:
                    log_lines = f.readlines()
                    last_10_lines = "".join(log_lines[-10:])
                messagebox.showerror("Error", f"An error occurred: {e}\n\nLast 10 lines of log:\n{last_10_lines}")
            except FileNotFoundError:
                messagebox.showerror("Error", f"An error occurred: {e}\n\nCould not find log file.")
            except Exception as log_e:
                messagebox.showerror("Error", f"An error occurred: {e}\n\nCould not read log file: {log_e}")

        finally:
            # --- FIX: Use .configure() and string states ---
            self.convert_button.configure(state="normal")
            self.cancel_button.configure(state="disabled")
            self.progress.stop()
            # --- FIX: Use .set() to reset progress bar ---
            if "Error" not in self.status_var.get():
                self.progress.set(1) # Keep it full on success
            else:
                self.progress.set(0) # Reset on error
            if self.status_var.get() == "Starting...": # Handle cancellation before start
                self.status_var.set("Ready")

    # --- FIX: Accept duration as an argument ---
    def _update_progress(self, duration):
        progress_file = "ffmpeg_progress.log"
        while self.conversion_thread.is_alive():
            try:
                with open(progress_file, "r") as f:
                    lines = f.readlines()
                    if lines:
                        last_line = lines[-1]
                        if "out_time_ms" in last_line:
                            time_ms = int(last_line.split("=")[1])
                            current_time_sec = time_ms / 1000000
                            # --- FIX: Calculate progress as 0.0-1.0 ---
                            if duration and duration > 0:
                                progress_value = max(0, min(1, current_time_sec / duration))
                                self.progress.set(progress_value)
            except (FileNotFoundError, IndexError, ValueError):
                pass
            time.sleep(0.1)

    def cancel_conversion(self):
        # This is still a difficult operation.
        # A more robust solution involves inter-thread communication
        # or sending a 'q' to the ffmpeg process.
        self.status_var.set("Cancellation requested...")
        messagebox.showinfo("Cancel", "Cancellation requested. The current operation will try to stop.")
        # A simple way to try and stop (if converter supports it):
        # You would need to build a way to signal the converter thread
        # to find and kill the ffmpeg subprocess.
        # For now, we just update the UI.
        self.convert_button.configure(state="normal")
        self.cancel_button.configure(state="disabled")


if __name__ == '__main__':
    root = customtkinter.CTk()
    gui = VideoConverterGUI(root)
    root.mainloop()
