import logging
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from tkinter.scrolledtext import ScrolledText
from typing import Optional, List

from downloaderyoutube.core.core import Downloader, VideoFormat
from downloaderyoutube.utils.logger import add_tkinter_handler, get_logger

# Get a logger instance for this module
logger = get_logger(__name__)

# A basic logging config dictionary for the Tkinter handler
LOGGING_CONFIG = {
    "colors": {
        logging.DEBUG: "gray",
        logging.INFO: "black",
        logging.WARNING: "orange",
        logging.ERROR: "red",
        logging.CRITICAL: "red",
    },
    "queue_poll_interval_ms": 100,
}


class App(tk.Frame):
    """
    The main graphical user interface for the Downloader application.
    """

    def __init__(self, master: tk.Tk):
        super().__init__(master)
        self.master = master
        self.downloader = Downloader()
        self.download_path: Optional[str] = None
        self.available_formats: List[VideoFormat] = []

        self.master.title("YouTube Downloader")
        self.master.geometry("800x600")

        self.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        self._create_widgets()
        self._setup_logging_handler()

    def _create_widgets(self):
        """Creates and lays out the widgets in the application window."""
        # --- Top Frame for URL Input ---
        url_frame = ttk.Frame(self)
        url_frame.pack(fill=tk.X, pady=(0, 5))

        ttk.Label(url_frame, text="Video URL:").pack(side=tk.LEFT, padx=(0, 5))
        self.url_entry = ttk.Entry(url_frame)
        self.url_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.analyze_button = ttk.Button(
            url_frame, text="Analizza URL", command=self._analyze_url
        )
        self.analyze_button.pack(side=tk.LEFT, padx=(5, 0))

        # --- Path Frame ---
        path_frame = ttk.Frame(self)
        path_frame.pack(fill=tk.X, pady=5)

        self.path_button = ttk.Button(
            path_frame, text="Choose Folder...", command=self.select_download_path
        )
        self.path_button.pack(side=tk.LEFT)
        self.path_label = ttk.Label(path_frame, text="No download folder selected.")
        self.path_label.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=10)

        # --- Format Selection Frame ---
        format_frame = ttk.Frame(self)
        format_frame.pack(fill=tk.X, pady=5)

        ttk.Label(format_frame, text="Formato:").pack(side=tk.LEFT, padx=(0, 5))
        self.format_combobox = ttk.Combobox(format_frame, state="readonly")
        self.format_combobox.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.download_button = ttk.Button(
            format_frame, text="Download", command=self.start_download, state="disabled"
        )
        self.download_button.pack(side=tk.LEFT, padx=(5, 0))

        # --- Progress Bar ---
        self.progress_bar = ttk.Progressbar(
            self, orient="horizontal", length=100, mode="determinate"
        )
        self.progress_bar.pack(fill=tk.X, pady=(10, 5))

        # --- Log Viewer ---
        log_frame = ttk.LabelFrame(self, text="Log")
        log_frame.pack(fill=tk.BOTH, expand=True)
        self.log_widget = ScrolledText(
            log_frame, state=tk.DISABLED, wrap=tk.WORD, font=("Courier New", 9)
        )
        self.log_widget.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

    def _setup_logging_handler(self):
        logger.info("Setting up GUI logging handler.")
        add_tkinter_handler(
            gui_log_widget=self.log_widget,
            root_tk_instance_for_gui_handler=self.master,
            logging_config_dict=LOGGING_CONFIG,
        )
        logger.info("GUI logging handler configured.")

    def select_download_path(self):
        path = filedialog.askdirectory()
        if path:
            self.download_path = path
            self.path_label.config(text=f"Saving to: {self.download_path}")
            logger.info(f"Download path set to: {self.download_path}")

    def _analyze_url(self):
        url = self.url_entry.get()
        if not url:
            messagebox.showerror("Error", "Please enter a YouTube URL.")
            return

        logger.info(f"Analyze button clicked. Fetching formats for {url}")
        self.analyze_button.config(state="disabled")
        self.download_button.config(state="disabled")
        self.format_combobox.set("Analisi in corso...")
        self.downloader.get_video_formats(url, self._on_formats_received)

    def _on_formats_received(self, formats: Optional[List[VideoFormat]]):
        # This is called from a different thread, so we schedule GUI updates
        self.master.after(0, self._update_formats_combobox, formats)

    def _update_formats_combobox(self, formats: Optional[List[VideoFormat]]):
        self.analyze_button.config(state="normal")
        if formats:
            logger.info("Successfully fetched formats. Populating combobox.")
            self.available_formats = formats
            self.format_combobox["values"] = [str(f) for f in formats]
            self.format_combobox.current(0)
            self.download_button.config(state="normal")
        else:
            logger.error("Failed to fetch video formats.")
            messagebox.showerror("Error", "Could not retrieve video formats. Check the URL and logs.")
            self.format_combobox.set("Analisi fallita.")
            self.format_combobox["values"] = []

    def start_download(self):
        url = self.url_entry.get()
        if not self.download_path:
            messagebox.showerror("Error", "Please select a download folder.")
            return

        selected_index = self.format_combobox.current()
        if selected_index < 0:
            messagebox.showerror("Error", "Please select a format to download.")
            return

        selected_format = self.available_formats[selected_index]
        logger.info(f"Download button clicked for format: {selected_format.format_id}")

        self.download_button.config(state="disabled")
        self.analyze_button.config(state="disabled")
        self.progress_bar["value"] = 0

        self.downloader.download_video(
            url=url,
            download_path=self.download_path,
            format_id=selected_format.format_id,
            progress_callback=self._on_download_progress,
            completion_callback=self._on_download_complete,
        )

    def _on_download_progress(self, percentage: int):
        self.master.after(0, self.progress_bar.config, {"value": percentage})

    def _on_download_complete(self, error_message: Optional[str]):
        self.master.after(0, self._finalize_download, error_message)

    def _finalize_download(self, error_message: Optional[str]):
        self.progress_bar["value"] = 0
        self.download_button.config(state="normal")
        self.analyze_button.config(state="normal")

        if error_message:
            messagebox.showerror("Download Failed", error_message)
        else:
            messagebox.showinfo("Success", "Video downloaded successfully!")