import customtkinter as ctk
from core.process_runner import ProcessRunner
from core import reporting
import threading
from tkinter import filedialog # Import for file dialog (for future wordlists)
import os

class OSINTFrame(ctk.CTkFrame):
    def __init__(self, master, set_session_callback=None, heading_font=None, text_font=None):
        super().__init__(master)
        self.set_session_callback = set_session_callback
        self.heading_font = heading_font if heading_font else ctk.CTkFont(size=18, weight="bold")
        self.text_font = text_font if text_font else ctk.CTkFont(size=12)
        self.monospace_font = ctk.CTkFont(family="Fira Code", size=12) # For output textboxes

        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(1, weight=1)

        title = ctk.CTkLabel(self, text="Sección de OSINT (Inteligencia de Fuentes Abiertas)", font=self.heading_font)
        title.grid(row=0, column=0, padx=20, pady=(20, 10), sticky="ew")

        self.tab_view = ctk.CTkTabview(self)
        self.tab_view.grid(row=1, column=0, padx=20, pady=10, sticky="nsew")

        self.tab_view.add("theHarvester")
        self.tab_view.add("Sherlock")
        self.tab_view.add("Metagoofil")

        self.theharvester_process_runner = None
        self.sherlock_process_runner = None
        self.metagoofil_process_runner = None # New attribute for Metagoofil
        self.current_session_name = None

        self.setup_theharvester_tab()
        self.setup_sherlock_tab()
        self.setup_metagoofil_tab() # Call the new setup method

    def setup_theharvester_tab(self):
        tab = self.tab_view.tab("theHarvester")
        tab.grid_columnconfigure(0, weight=1)
        tab.grid_rowconfigure(4, weight=1) # Adjusted for output textbox vertical expansion

        # ---- Input Controls Frame ----
        input_controls_frame = ctk.CTkFrame(tab)
        input_controls_frame.grid(row=0, column=0, padx=10, pady=10, sticky="ew")
        input_controls_frame.grid_columnconfigure(0, weight=1)
        input_controls_frame.grid_columnconfigure(1, weight=2) # Entry wider than label

        # Target Domain
        self.theharvester_domain_label = ctk.CTkLabel(input_controls_frame, text="Dominio Objetivo:")
        self.theharvester_domain_label.grid(row=0, column=0, padx=10, pady=8, sticky="w")
        self.theharvester_domain_entry = ctk.CTkEntry(input_controls_frame, placeholder_text="ej: example.com")
        self.theharvester_domain_entry.grid(row=0, column=1, padx=10, pady=8, sticky="ew")

        # Data Sources
        self.theharvester_sources_label = ctk.CTkLabel(input_controls_frame, text="Fuentes (separadas por coma):")
        self.theharvester_sources_label.grid(row=1, column=0, padx=10, pady=8, sticky="w")
        self.theharvester_sources_entry = ctk.CTkEntry(input_controls_frame, placeholder_text="ej: google,linkedin,twitter")
        self.theharvester_sources_entry.grid(row=1, column=1, padx=10, pady=8, sticky="ew")
        
        # ---- Action Buttons Frame ----
        action_buttons_frame = ctk.CTkFrame(tab)
        action_buttons_frame.grid(row=1, column=0, padx=10, pady=10, sticky="ew")
        action_buttons_frame.grid_columnconfigure(0, weight=1)
        action_buttons_frame.grid_columnconfigure(1, weight=1)

        self.theharvester_start_button = ctk.CTkButton(action_buttons_frame, text="Iniciar theHarvester", command=self.start_theharvester_scan)
        self.theharvester_start_button.grid(row=0, column=0, padx=10, pady=12, sticky="ew")

        self.theharvester_stop_button = ctk.CTkButton(action_buttons_frame, text="Detener theHarvester", command=self.stop_theharvester_scan, fg_color="red", state="disabled")
        self.theharvester_stop_button.grid(row=0, column=1, padx=10, pady=12, sticky="ew")
        
        # ---- Status and Progress Indicators ----
        self.theharvester_status_label = ctk.CTkLabel(tab, text="Listo", font=self.text_font)
        self.theharvester_status_label.grid(row=2, column=0, padx=10, pady=(5, 0), sticky="w")

        self.theharvester_progress_bar = ctk.CTkProgressBar(tab, mode="indeterminate")
        self.theharvester_progress_bar.grid(row=3, column=0, padx=10, pady=(0, 5), sticky="ew")
        self.theharvester_progress_bar.set(0) # Hide it initially
        
        # ---- Output ----
        self.theharvester_output_textbox = ctk.CTkTextbox(tab, state="disabled", font=self.monospace_font)
        self.theharvester_output_textbox.grid(row=4, column=0, padx=10, pady=10, sticky="nsew")

    def start_theharvester_scan(self):
        domain = self.theharvester_domain_entry.get()
        sources = self.theharvester_sources_entry.get()
        if not domain:
            return

        self.theharvester_start_button.configure(state="disabled")
        self.theharvester_stop_button.configure(state="normal")
        
        self.theharvester_status_label.configure(text="Iniciando theHarvester...", text_color="orange")
        self.theharvester_progress_bar.start()

        self.current_session_name = reporting.create_session(domain)
        if self.set_session_callback:
            self.set_session_callback(self.current_session_name)
        
        # Construct the explicit path to theharvester executable and the venv's python interpreter
        current_working_directory = os.getcwd()
        python_interpreter_path = os.path.join(current_working_directory, "Cyber-Godfather", "venv", "bin", "python3")
        theharvester_script_path = os.path.join(current_working_directory, "Cyber-Godfather", "venv", "bin", "theHarvester")
        
        command = [python_interpreter_path, theharvester_script_path, "-d", domain]
        if sources:
            command.extend(["-b", sources])
        # command.append("-v") # Verbose output - Removed as it's an unrecognized argument in v4.10.0

        self.theharvester_output_textbox.configure(state="normal")
        self.theharvester_output_textbox.delete("1.0", "end")
        self.theharvester_output_textbox.insert("1.0", f"--- Iniciando theHarvester en {domain} ---\nComando: {' '.join(command)}\n\n")
        self.theharvester_output_textbox.configure(state="disabled")

        self.theharvester_process_runner = ProcessRunner(command, self.theharvester_output_textbox)
        self.theharvester_process_runner.start()
        
        threading.Thread(target=self.wait_and_save_theharvester, daemon=True).start()

    def stop_theharvester_scan(self):
        if self.theharvester_process_runner:
            self.theharvester_process_runner.stop()
            self.theharvester_start_button.configure(state="normal")
            self.theharvester_stop_button.configure(state="disabled")
            self.theharvester_status_label.configure(text="Detenido.", text_color="red")
            self.theharvester_progress_bar.stop()

    def wait_and_save_theharvester(self):
        if self.theharvester_process_runner:
            self.theharvester_process_runner.thread.join()

        full_output = self.theharvester_output_textbox.get("1.0", "end")
        reporting.log_tool_output(self.current_session_name, "theHarvester Scan", full_output, output_format="txt")
        
        self.master.after(0, self._reset_theharvester_buttons)

    def _reset_theharvester_buttons(self):
        self.theharvester_start_button.configure(state="normal")
        self.theharvester_stop_button.configure(state="disabled")
        self.theharvester_status_label.configure(text="Completado.", text_color="green")
        self.theharvester_progress_bar.stop()

    # ---- SHERLOCK TAB ----
    def setup_sherlock_tab(self):
        tab = self.tab_view.tab("Sherlock")
        tab.grid_columnconfigure(0, weight=1)
        tab.grid_rowconfigure(4, weight=1) # Adjusted for output textbox vertical expansion

        # ---- Input Controls Frame ----
        input_controls_frame = ctk.CTkFrame(tab)
        input_controls_frame.grid(row=0, column=0, padx=10, pady=10, sticky="ew")
        input_controls_frame.grid_columnconfigure(0, weight=1)

        self.sherlock_username_entry = ctk.CTkEntry(input_controls_frame, placeholder_text="Nombre de usuario (ej: johndoe)")
        self.sherlock_username_entry.grid(row=0, column=0, padx=10, pady=8, sticky="ew")

        # ---- Action Buttons Frame ----
        buttons_frame = ctk.CTkFrame(tab)
        buttons_frame.grid(row=1, column=0, padx=10, pady=10, sticky="ew")
        buttons_frame.grid_columnconfigure(0, weight=1)
        buttons_frame.grid_columnconfigure(1, weight=1)

        self.sherlock_start_button = ctk.CTkButton(buttons_frame, text="Iniciar Sherlock", command=self.start_sherlock_scan)
        self.sherlock_start_button.grid(row=0, column=0, padx=10, pady=12, sticky="ew")

        self.sherlock_stop_button = ctk.CTkButton(buttons_frame, text="Detener Sherlock", command=self.stop_sherlock_scan, fg_color="red", state="disabled")
        self.sherlock_stop_button.grid(row=0, column=1, padx=10, pady=12, sticky="ew")
        
        # ---- Status and Progress Indicators ----
        self.sherlock_status_label = ctk.CTkLabel(tab, text="Listo", font=self.text_font)
        self.sherlock_status_label.grid(row=2, column=0, padx=10, pady=(5, 0), sticky="w")

        self.sherlock_progress_bar = ctk.CTkProgressBar(tab, mode="indeterminate")
        self.sherlock_progress_bar.grid(row=3, column=0, padx=10, pady=(0, 5), sticky="ew")
        self.sherlock_progress_bar.set(0) # Hide it initially
        
        # ---- Output ----
        self.sherlock_output_textbox = ctk.CTkTextbox(tab, state="disabled", font=self.monospace_font)
        self.sherlock_output_textbox.grid(row=4, column=0, padx=10, pady=10, sticky="nsew")

    def start_sherlock_scan(self):
        username = self.sherlock_username_entry.get()
        if not username:
            return

        self.sherlock_start_button.configure(state="disabled")
        self.sherlock_stop_button.configure(state="normal")
        
        self.sherlock_status_label.configure(text="Iniciando Sherlock...", text_color="orange")
        self.sherlock_progress_bar.start()

        self.current_session_name = reporting.create_session(username) # Use username as target for reporting
        if self.set_session_callback:
            self.set_session_callback(self.current_session_name)
        
        # Construct the explicit path to the sherlock executable and the venv's python interpreter
        current_working_directory = os.getcwd()
        python_interpreter_path = os.path.join(current_working_directory, "Cyber-Godfather", "venv", "bin", "python3")
        sherlock_script_path = os.path.join(current_working_directory, "Cyber-Godfather", "venv", "bin", "sherlock")
        
        command = [python_interpreter_path, sherlock_script_path, username]

        self.sherlock_output_textbox.configure(state="normal")
        self.sherlock_output_textbox.delete("1.0", "end")
        self.sherlock_output_textbox.insert("1.0", f"--- Iniciando Sherlock para {username} ---\nComando: {' '.join(command)}\n\n")
        self.sherlock_output_textbox.configure(state="disabled")

        self.sherlock_process_runner = ProcessRunner(
            command,
            self.sherlock_output_textbox,
            status_label=self.sherlock_status_label,
            progress_bar=self.sherlock_progress_bar
        )
        self.sherlock_process_runner.start()
        
        threading.Thread(target=self.wait_and_save_sherlock, daemon=True).start()

    def stop_sherlock_scan(self):
        if self.sherlock_process_runner:
            self.sherlock_process_runner.stop()
            self.sherlock_start_button.configure(state="normal")
            self.sherlock_stop_button.configure(state="disabled")
            self.sherlock_status_label.configure(text="Detenido.", text_color="red")
            self.sherlock_progress_bar.stop()

    def wait_and_save_sherlock(self):
        if self.sherlock_process_runner:
            self.sherlock_process_runner.thread.join()

        full_output = self.sherlock_output_textbox.get("1.0", "end")
        reporting.log_tool_output(self.current_session_name, "Sherlock Scan", full_output, output_format="txt")
        
        self.master.after(0, self._reset_sherlock_buttons)

    def _reset_sherlock_buttons(self):
        self.sherlock_start_button.configure(state="normal")
        self.sherlock_stop_button.configure(state="disabled")
        self.sherlock_status_label.configure(text="Completado.", text_color="green")
        self.sherlock_progress_bar.stop()

    # ---- METAGOOFILE TAB ----
    def setup_metagoofil_tab(self):
        tab = self.tab_view.tab("Metagoofil")
        tab.grid_columnconfigure(0, weight=1)
        tab.grid_rowconfigure(4, weight=1) # Adjusted for output textbox vertical expansion

        # ---- Input Controls Frame ----
        input_controls_frame = ctk.CTkFrame(tab)
        input_controls_frame.grid(row=0, column=0, padx=10, pady=10, sticky="ew")
        input_controls_frame.grid_columnconfigure(0, weight=1)
        input_controls_frame.grid_columnconfigure(1, weight=2) # Entry wider than label

        # Target Domain
        self.metagoofil_domain_label = ctk.CTkLabel(input_controls_frame, text="Dominio Objetivo:")
        self.metagoofil_domain_label.grid(row=0, column=0, padx=10, pady=8, sticky="w")
        self.metagoofil_domain_entry = ctk.CTkEntry(input_controls_frame, placeholder_text="ej: example.com")
        self.metagoofil_domain_entry.grid(row=0, column=1, padx=10, pady=8, sticky="ew")

        # File Types
        self.metagoofil_filetypes_label = ctk.CTkLabel(input_controls_frame, text="Tipos de Archivo (separados por coma):")
        self.metagoofil_filetypes_label.grid(row=1, column=0, padx=10, pady=8, sticky="w")
        self.metagoofil_filetypes_entry = ctk.CTkEntry(input_controls_frame, placeholder_text="ej: pdf,doc,xls")
        self.metagoofil_filetypes_entry.grid(row=1, column=1, padx=10, pady=8, sticky="ew")
        
        # Limit
        self.metagoofil_limit_label = ctk.CTkLabel(input_controls_frame, text="Límite de Resultados (-l):")
        self.metagoofil_limit_label.grid(row=2, column=0, padx=10, pady=8, sticky="w")
        self.metagoofil_limit_entry = ctk.CTkEntry(input_controls_frame, placeholder_text="ej: 100")
        self.metagoofil_limit_entry.grid(row=2, column=1, padx=10, pady=8, sticky="ew")

        # ---- Action Buttons Frame ----
        action_buttons_frame = ctk.CTkFrame(tab)
        action_buttons_frame.grid(row=1, column=0, padx=10, pady=10, sticky="ew")
        action_buttons_frame.grid_columnconfigure(0, weight=1)
        action_buttons_frame.grid_columnconfigure(1, weight=1)

        self.metagoofil_start_button = ctk.CTkButton(action_buttons_frame, text="Iniciar Metagoofil", command=self.start_metagoofil_scan)
        self.metagoofil_start_button.grid(row=0, column=0, padx=10, pady=12, sticky="ew")

        self.metagoofil_stop_button = ctk.CTkButton(action_buttons_frame, text="Detener Metagoofil", command=self.stop_metagoofil_scan, fg_color="red", state="disabled")
        self.metagoofil_stop_button.grid(row=0, column=1, padx=10, pady=12, sticky="ew")
        
        # ---- Status and Progress Indicators ----
        self.metagoofil_status_label = ctk.CTkLabel(tab, text="Listo", font=self.text_font)
        self.metagoofil_status_label.grid(row=2, column=0, padx=10, pady=(5, 0), sticky="w")

        self.metagoofil_progress_bar = ctk.CTkProgressBar(tab, mode="indeterminate")
        self.metagoofil_progress_bar.grid(row=3, column=0, padx=10, pady=(0, 5), sticky="ew")
        self.metagoofil_progress_bar.set(0) # Hide it initially
        
        # ---- Output ----
        self.metagoofil_output_textbox = ctk.CTkTextbox(tab, state="disabled", font=self.monospace_font)
        self.metagoofil_output_textbox.grid(row=4, column=0, padx=10, pady=10, sticky="nsew")

    def start_metagoofil_scan(self):
        domain = self.metagoofil_domain_entry.get()
        filetypes = self.metagoofil_filetypes_entry.get()
        limit = self.metagoofil_limit_entry.get()
        
        if not domain:
            return

        self.metagoofil_start_button.configure(state="disabled")
        self.metagoofil_stop_button.configure(state="normal")
        
        self.metagoofil_status_label.configure(text="Iniciando Metagoofil...", text_color="orange")
        self.metagoofil_progress_bar.start()

        self.current_session_name = reporting.create_session(domain) # Use domain as target for reporting
        if self.set_session_callback:
            self.set_session_callback(self.current_session_name)
        
        command = [python_interpreter_path, metagoofil_script_path, "-d", domain]
        if filetypes:
            command.extend(["-t", filetypes])
        if limit and limit.isdigit():
            command.extend(["-l", limit])

        self.metagoofil_output_textbox.configure(state="normal")
        self.metagoofil_output_textbox.delete("1.0", "end")
        self.metagoofil_output_textbox.insert("1.0", f"--- Iniciando Metagoofil para {domain} ---\nComando: {' '.join(command)}\n\n")
        self.metagoofil_output_textbox.configure(state="disabled")

        metagoofil_cwd = os.path.join(current_working_directory, "Cyber-Godfather", "tools", "metagoofil")

        self.metagoofil_process_runner = ProcessRunner(
            command,
            self.metagoofil_output_textbox,
            cwd=metagoofil_cwd,
            status_label=self.metagoofil_status_label,
            progress_bar=self.metagoofil_progress_bar
        )
        self.metagoofil_process_runner.start()
        
        threading.Thread(target=self.wait_and_save_metagoofil, daemon=True).start()

    def stop_metagoofil_scan(self):
        if self.metagoofil_process_runner:
            self.metagoofil_process_runner.stop()
            self.metagoofil_start_button.configure(state="normal")
            self.metagoofil_stop_button.configure(state="disabled")
            self.metagoofil_status_label.configure(text="Detenido.", text_color="red")
            self.metagoofil_progress_bar.stop()

    def wait_and_save_metagoofil(self):
        if self.metagoofil_process_runner:
            self.metagoofil_process_runner.thread.join()

        full_output = self.metagoofil_output_textbox.get("1.0", "end")
        reporting.log_tool_output(self.current_session_name, "Metagoofil Scan", full_output, output_format="txt")
        
        self.master.after(0, self._reset_metagoofil_buttons)

    def _reset_metagoofil_buttons(self):
        self.metagoofil_start_button.configure(state="normal")
        self.metagoofil_stop_button.configure(state="disabled")
        self.metagoofil_status_label.configure(text="Completado.", text_color="green")
        self.metagoofil_progress_bar.stop()
