# markdownconverter/gui/batch_converter.py

import os
import tkinter as tk
from pathlib import Path
from tkinter import filedialog, messagebox, StringVar, BooleanVar
import ttkbootstrap as tb
from tkinter.scrolledtext import ScrolledText
from ttkbootstrap.constants import *

from ..core.core import (
    combine_markdown_files, 
    convert_markdown_to_docx_with_pandoc, 
    convert_docx_to_pdf
)
from ..utils.logger import get_logger

log = get_logger(__name__)


class BatchConverterTab(tb.Frame):
    """
    Tab per la conversione batch di file markdown da una cartella.
    Trova tutti i file markdown numerati (es. 01_*.md, 02_*.md),
    li combina in ordine alfabetico e genera DOCX e/o PDF.
    """
    
    def __init__(self, parent):
        super().__init__(parent, padding=10)
        
        self.folder_path = StringVar()
        self.output_name = StringVar(value="manuale")
        self.template_path = StringVar()
        self.use_template = BooleanVar(value=False)
        self.generate_pdf = BooleanVar(value=True)
        
        self._build_ui()
    
    def _build_ui(self):
        """Costruisce l'interfaccia utente del tab batch."""
        
        # Frame per la selezione della cartella
        folder_frame = tb.Labelframe(self, text="Cartella Sorgente", padding=10)
        folder_frame.pack(fill=tk.X, pady=(0, 10))
        folder_frame.columnconfigure(1, weight=1)
        
        tb.Label(folder_frame, text="Cartella Markdown:").grid(
            row=0, column=0, padx=5, pady=5, sticky="w"
        )
        tb.Entry(folder_frame, textvariable=self.folder_path).grid(
            row=0, column=1, padx=5, pady=5, sticky="ew"
        )
        tb.Button(
            folder_frame, 
            text="Sfoglia...", 
            command=self._choose_folder,
            bootstyle=PRIMARY
        ).grid(row=0, column=2, padx=5, pady=5)
        
        # Frame per le opzioni
        options_frame = tb.Labelframe(self, text="Opzioni di Conversione", padding=10)
        options_frame.pack(fill=tk.X, pady=(0, 10))
        options_frame.columnconfigure(1, weight=1)
        
        tb.Label(options_frame, text="Nome base output:").grid(
            row=0, column=0, padx=5, pady=5, sticky="w"
        )
        tb.Entry(options_frame, textvariable=self.output_name).grid(
            row=0, column=1, padx=5, pady=5, sticky="ew"
        )
        
        # Checkbox per template
        tb.Checkbutton(
            options_frame, 
            text="Usa template DOCX", 
            variable=self.use_template,
            command=self._toggle_template,
            bootstyle="primary-round-toggle"
        ).grid(row=1, column=0, padx=5, pady=5, sticky="w")
        
        # Frame per template
        self.template_entry = tb.Entry(
            options_frame, 
            textvariable=self.template_path,
            state="disabled"
        )
        self.template_entry.grid(row=1, column=1, padx=5, pady=5, sticky="ew")
        
        self.template_button = tb.Button(
            options_frame, 
            text="Seleziona template", 
            command=self._choose_template,
            state="disabled"
        )
        self.template_button.grid(row=1, column=2, padx=5, pady=5)
        
        # Checkbox per PDF
        tb.Checkbutton(
            options_frame, 
            text="Genera anche PDF finale", 
            variable=self.generate_pdf,
            bootstyle="primary-round-toggle"
        ).grid(row=2, column=0, columnspan=2, padx=5, pady=5, sticky="w")
        
        # Pulsante di conversione
        tb.Button(
            self, 
            text="Genera Documento", 
            command=self._generate_output,
            bootstyle=SUCCESS,
            width=20
        ).pack(pady=10)
        # Frame che mostra la lista dei file trovati nella cartella selezionata
        files_frame = tb.Labelframe(self, text="File trovati (in ordine alfabetico)", padding=10)
        files_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
        files_frame.rowconfigure(0, weight=1); files_frame.columnconfigure(0, weight=1)
        self.files_listbox = tk.Listbox(files_frame, height=8, exportselection=False)
        self.files_listbox.grid(row=0, column=0, sticky="nsew")
        files_scroll = tb.Scrollbar(files_frame, orient=tk.VERTICAL, command=self.files_listbox.yview)
        files_scroll.grid(row=0, column=1, sticky="ns")
        self.files_listbox.config(yscrollcommand=files_scroll.set)

        # Log area
        log_frame = tb.Labelframe(self, text="Log", padding=10)
        log_frame.pack(fill=tk.BOTH, expand=True)
        
        self.log_box = ScrolledText(log_frame, height=15, state="disabled", wrap=tk.WORD)
        self.log_box.pack(fill=tk.BOTH, expand=True)
    
    def _log(self, text):
        """Aggiunge un messaggio all'area log."""
        self.log_box.configure(state="normal")
        self.log_box.insert(tk.END, text + "\n")
        self.log_box.configure(state="disabled")
        self.log_box.see(tk.END)
        self.update_idletasks()
    
    def _choose_folder(self):
        """Apre il dialogo per selezionare la cartella."""
        folder = filedialog.askdirectory(title="Seleziona la cartella Markdown")
        if folder:
            self.folder_path.set(folder)
            self._log(f"Cartella selezionata: {folder}")
            # Aggiorna immediatamente la lista dei file trovati
            try:
                self._scan_and_display_files(folder)
            except Exception as e:
                log.error(f"Errore durante la scansione della cartella: {e}", exc_info=True)
    
    def _toggle_template(self):
        """Attiva/disattiva i controlli del template."""
        state = "normal" if self.use_template.get() else "disabled"
        self.template_entry.configure(state=state)
        self.template_button.configure(state=state)
    
    def _choose_template(self):
        """Apre il dialogo per selezionare il template."""
        file = filedialog.askopenfilename(
            title="Seleziona template DOCX",
            filetypes=[("Word Documents", "*.docx"), ("Word Templates", "*.dotx")]
        )
        if file:
            self.template_path.set(file)
            self._log(f"Template selezionato: {os.path.basename(file)}")
    
    def _generate_output(self):
        """Esegue la conversione batch dei file markdown."""
        folder = self.folder_path.get().strip()
        output_name = self.output_name.get().strip()
        template = self.template_path.get().strip()
        use_template = self.use_template.get()
        make_pdf = self.generate_pdf.get()
        
        # Validazione input
        if not folder:
            messagebox.showwarning(
                "Attenzione", 
                "Seleziona una cartella contenente i file Markdown."
            )
            return
        
        if not output_name:
            messagebox.showwarning(
                "Attenzione", 
                "Inserisci un nome per il file di output."
            )
            return
        
        folder_path = Path(folder)
        if not folder_path.exists():
            messagebox.showerror("Errore", "La cartella selezionata non esiste.")
            return
        
        # Trova i file markdown numerati
        md_files = sorted(folder_path.glob("[0-9][0-9]_*.md"))
        if not md_files:
            messagebox.showerror(
                "Errore", 
                "Nessun file Markdown numerato trovato nella cartella.\n"
                "I file devono seguire il pattern: 01_nome.md, 02_nome.md, ecc."
            )
            return

        # Mostra una finestra di conferma con la lista dei file trovati
        if not self._confirm_file_list(md_files):
            self._log("Operazione annullata dall'utente dopo la visualizzazione dei file.")
            return
        
        self._log(f"\n{'='*60}")
        self._log(f"INIZIO CONVERSIONE BATCH")
        self._log(f"{'='*60}")
        self._log(f"Trovati {len(md_files)} file Markdown:")
        for f in md_files:
            self._log(f"  - {f.name}")
        
        # Prepara i percorsi di output
        output_docx = folder_path / f"{output_name}.docx"
        output_pdf = folder_path / f"{output_name}.pdf"
        combined_md = folder_path / "_manuale_unico_temp.md"
        
        try:
            # Combina i file markdown
            self._log(f"\nUnione dei file in {combined_md.name}...")
            combine_markdown_files(md_files, combined_md)
            self._log("✅ File unito con successo.")
            
            # Genera DOCX
            self._log("\nGenerazione DOCX...")
            if use_template:
                if not Path(template).exists():
                    messagebox.showerror(
                        "Template non trovato", 
                        f"Il file {template} non esiste."
                    )
                    return
                convert_markdown_to_docx_with_pandoc(
                    str(combined_md), 
                    str(output_docx),
                    template_path=template
                )
            else:
                convert_markdown_to_docx_with_pandoc(
                    str(combined_md), 
                    str(output_docx)
                )
            
            self._log(f"✅ DOCX generato: {output_docx.name}")
            
            # Genera PDF opzionale
            if make_pdf:
                self._log("\nGenerazione PDF dal DOCX...")
                convert_docx_to_pdf(str(output_docx), str(output_pdf))
                self._log(f"✅ PDF generato: {output_pdf.name}")
                messagebox.showinfo(
                    "Completato", 
                    f"Conversione completata con successo!\n\n"
                    f"DOCX: {output_docx.name}\n"
                    f"PDF: {output_pdf.name}"
                )
            else:
                messagebox.showinfo(
                    "Completato", 
                    f"Conversione completata con successo!\n\n"
                    f"DOCX: {output_docx.name}"
                )
            
            self._log(f"\n{'='*60}")
            self._log("CONVERSIONE COMPLETATA CON SUCCESSO")
            self._log(f"{'='*60}\n")
            
        except Exception as e:
            log.error(f"Errore durante la conversione batch: {e}", exc_info=True)
            self._log(f"\n❌ ERRORE: {str(e)}")
            messagebox.showerror(
                "Errore", 
                f"Si è verificato un errore durante la conversione:\n\n{str(e)}"
            )
        finally:
            # Pulisce il file temporaneo
            if combined_md.exists():
                combined_md.unlink()
                self._log(f"File temporaneo {combined_md.name} rimosso.")

    def _scan_and_display_files(self, folder: str):
        """Scansiona la cartella e popola la listbox con i file markdown trovati.

        Il pattern usato corrisponde ai file numerati: 01_nome.md, 02_nome.md, ...
        """
        folder_path = Path(folder)
        if not folder_path.exists():
            raise FileNotFoundError("La cartella selezionata non esiste.")
        md_files = sorted(folder_path.glob("[0-9][0-9]_*.md"))
        # Pulisce la listbox
        self.files_listbox.delete(0, tk.END)
        for f in md_files:
            self.files_listbox.insert(tk.END, f.name)
        self._log(f"Scansionati {len(md_files)} file markdown nella cartella.")

    def _confirm_file_list(self, md_files: list) -> bool:
        """Apre una finestra modale che mostra la lista dei file trovati e chiede conferma all'utente.

        Restituisce True se l'utente conferma, False se annulla.
        """
        dlg = tb.Toplevel(self, title="Conferma file trovati")
        dlg.transient(self)
        dlg.grab_set()
        dlg.geometry("600x400")
        tb.Label(dlg, text="I seguenti file sono stati trovati e saranno uniti in questo ordine:", bootstyle=INFO).pack(anchor="w", padx=10, pady=(10, 0))
        list_frame = tb.Frame(dlg); list_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        listbox = tk.Listbox(list_frame)
        listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar = tb.Scrollbar(list_frame, orient=tk.VERTICAL, command=listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        listbox.config(yscrollcommand=scrollbar.set)
        for f in md_files:
            listbox.insert(tk.END, f.name)

        btn_frame = tb.Frame(dlg); btn_frame.pack(fill=tk.X, pady=(0, 10), padx=10)
        confirmed = {"value": False}

        def _on_confirm():
            confirmed["value"] = True
            dlg.grab_release(); dlg.destroy()

        def _on_cancel():
            dlg.grab_release(); dlg.destroy()

        tb.Button(btn_frame, text="Conferma e procedi", bootstyle=SUCCESS, command=_on_confirm).pack(side=tk.RIGHT, padx=5)
        tb.Button(btn_frame, text="Annulla", bootstyle=SECONDARY, command=_on_cancel).pack(side=tk.RIGHT)

        self.wait_window(dlg)
        return confirmed["value"]
