"""
Frame Delete Retrieval Module.

This module provides a GUI panel for managing retrieval operations including
deletion from archive and database, comment management, and retrieval resumption.
"""

import os
import traceback
from pathlib import Path

import pandas as pd
from tkinter import messagebox
from numpy.random import randint

from GUIBRUSHR.GUI.DataInterface.DBSQLite3 import DBSQLite3
from GUIBRUSHR.GUI.LAYOUT.MyPanel import MyPanel
from GUIBRUSHR.GUI.WIDGET.MyButton import MyButton
from GUIBRUSHR.GUI.WIDGET.MyCheckBox import MyCheckBox
from GUIBRUSHR.GUI.WIDGET.MyEntry import MyEntry
from GUIBRUSHR.GUI.WIDGET.MyTextField import MyTextField
from GUIBRUSHR.General_Constants.FunctionsAndConstants.Constant_Variables import ConstantVariables
from GUIBRUSHR.General_Constants.Classes.HelpButton import HelpButton
from GUIBRUSHR.General_Constants.FunctionsAndConstants.general_functions import get_csv_value


class FrameDeleteRetrieval(MyPanel):
    """
    GUI panel for managing retrieval operations.
    
    This class provides functionality for:
    - Deleting retrievals from archive and/or database
    - Managing comments for retrievals
    - Resuming interrupted retrievals
    - Displaying retrieval information
    """

    def __init__(self, parent, color, row, column, path_default, frame_input, window, **kwargs):
        """
        Initialize the FrameDeleteRetrieval panel.
        
        Args:
            parent: Parent widget
            color: Background color for the panel
            row: Grid row position
            column: Grid column position
            path_default: Default path for database operations
            frame_input: Reference to the input frame
            window: Main window reference
            **kwargs: Additional keyword arguments passed to parent
        """
        super().__init__(parent, color, row, column, **kwargs)
        
        # Initialize core attributes
        self.path_folder_targets = frame_input.frame_input.frame_path.path_folder_targets.get_text()
        self.window = window
        self.path_default = path_default
        self.frame_input = frame_input
        
        # Initialize working variables
        self.folder_retrieval = None
        self.prefix_file = None
        self.underscore = None
        self.p = None
        self.filepng = None
        self.lista_parametri = None
        self.path_imm = None
        self.last_plot_reduced = None
        self.global_exc = 1
        
        # Create main panels
        self.panel_delete = MyPanel(self, color, 0, 1)
        self.panel_resume = MyPanel(self, color, 0, 2)

        # Create help button
        self._create_help_button()

        # Initialize UI components
        self._setup_delete_panel(color)
        self._setup_resume_panel(color)

    def _setup_delete_panel(self, color):
        """Set up the deletion panel with buttons and text fields."""
        # Delete buttons
        self.button_delete_1 = MyButton(
            self.panel_delete, 0, 1, 'DELETE RETRIEVAL FROM ARCHIVE', '#f5004a',
            self.delete_from_archive, color_panel=color, columnspan=15, width=60
        )
        
        self.button_delete_2 = MyButton(
            self.panel_delete, 1, 1, 'DELETE RETRIEVAL FROM DB', '#00674a',
            self.delete_from_database, color_panel=color, columnspan=15, width=60
        )
        
        self.button_delete_3 = MyButton(
            self.panel_delete, 2, 1, 'DELETE RETRIEVAL BOTH FROM ARCHIVE AND DB', '#B0A74a',
            self.delete_from_both, color_panel=color, columnspan=15, width=60
        )
        
        # Comments section
        self.textfield_comments = MyTextField(
            self.panel_delete, 3, 1, "", "Comments:", color=color,
            columnspan=15, width=40, height=10
        )
        
        self.button_show_comment = MyButton(
            self.panel_delete, 4, 1, 'SHOW COMMENT', '#6C004a',
            self.show_comment, color_panel=color, columnspan=1, sticky="NSW"
        )
        
        self.button_update_comment = MyButton(
            self.panel_delete, 4, 9, 'UPDATE COMMENT', '#f5674a',
            self.update_comment, color_panel=color, columnspan=8, sticky="NSE"
        )

    def _create_help_button(self):
        """Create help button with widget descriptions."""
        help_text = {
            "DELETE RETRIEVAL FROM ARCHIVE button": "Permanently deletes all retrieval result files (MCMC chains, plots, pickles) from the file system. Database entry remains untouched. Use this to free disk space while keeping database records.",

            "DELETE RETRIEVAL FROM DB button": "Removes the retrieval entry from the SQLite database. Result files in the archive remain untouched. Use this to clean the database while preserving raw results for potential re-import.",

            "DELETE RETRIEVAL BOTH FROM ARCHIVE AND DB button": "Completely removes the retrieval from both the database and file system. This is permanent and cannot be undone. Use with caution.",

            "Comments field": "Text field for viewing and editing user comments associated with a retrieval run. Comments are stored in the retrieval's df_general_info.csv file and help document analysis notes, interpretations, or issues encountered.",

            "SHOW COMMENT button": "Load and display existing comments for the selected retrieval in the Comments field.",

            "UPDATE COMMENT button": "Save the current text in the Comments field to the selected retrieval's df_general_info.csv file. Overwrites any existing comments.",

            "Use taskset command checkbox": "Enable Linux taskset command to assign retrieval processes to specific CPU cores. Helps prevent CPU contention when running multiple retrievals simultaneously.",

            "Final core field": "Highest CPU core number to use. Initial core is calculated as (final_core - nchains - 1). For example, with 8 chains and final_core=20, cores 12-20 will be used.",

            "Priority threads field": "Nice value for retrieval process priority. Range: -20 (highest priority) to 19 (lowest priority). Default: 19 (low priority to avoid interfering with other processes).",

            "RESUME RETRIEVAL button": "Continue a previously interrupted retrieval using existing MCMC chains as starting points. Generates a new random seed to ensure independent sampling. Useful for extending runs that haven't converged or adding more iterations.",

            "DISPLAY INFO RETRIEVAL button": "Show metadata about the selected retrieval, including the random seed used for MCMC initialization.",

            "Information field": "Display area for retrieval metadata such as random seed, creation date, and other diagnostic information."
        }

        self.help_button = HelpButton(
            self, 0, 0,
            "Delete/Resume Retrieval Panel Help",
            help_text,
            columnspan=1
        )

    def _setup_resume_panel(self, color):
        """Set up the resume panel with controls and information display."""
        # Taskset checkbox
        self.checkbox_use_taskset = MyCheckBox(
            self.panel_resume, 0, 1, "Use taskset command"
        )
        
        # Core and priority settings
        self.entry_end_core = MyEntry(
            self.panel_resume, 1, 0, str(ConstantVariables.ncore),
            "Final core\n(initial will be\nfinal - nchain - 1)", color=color
        )
        
        self.entry_priority_process = MyEntry(
            self.panel_resume, 2, 0, "18", "Priority threads", color=color
        )
        
        # Action buttons
        self.button_resume = MyButton(
            self.panel_resume, 3, 1, 'RESUME RETRIEVAL', '#5782ff',
            self.resume_retrieval, color_panel=color, columnspan=1, sticky="NSW"
        )
        
        self.button_show_info = MyButton(
            self.panel_resume, 3, 3, 'DISPLAY INFO RETRIEVAL', '#8d57ff',
            self.display_info_retrieval, color_panel=color, columnspan=1, sticky="NSE"
        )
        
        # Information display
        self.textfield_information = MyTextField(
            self.panel_resume, 4, 1, "", "Information:", color=color,
            columnspan=15, width=40, height=20
        )

    def delete_from_archive(self):
        """Delete retrieval files from the archive directory only."""
        target, arr_values, selected_name = self.get_row()
        if target is None:
            return

        # Confirmation dialog
        retrieval_id = arr_values[ConstantVariables.DICT_FILTER_TABLE["ID"]["index"]]
        confirm = messagebox.askyesno(
            "Confirm Deletion",
            f"Are you sure you want to delete retrieval '{retrieval_id}' from the archive?\n\n"
            f"This will permanently delete all files (MCMC chains, plots, pickles).\n"
            f"The database entry will remain intact.\n\n"
            f"This action cannot be undone."
        )

        if not confirm:
            return

        # Get target from dropdown (preserving original logic)
        target = self.frame_input.frame_filter_table.frame_filter.dropdown_target.get_value()

        # Construct path to target directory
        path_target = str(Path(
            self.path_folder_targets, target, ConstantVariables.RESULTS_FOLDER,
            retrieval_id
        ))

        # Remove directory and contents
        os.system("rm -rf " + path_target)
        messagebox.showinfo("Deleted", "Retrieval deleted from archive successfully.")

    def delete_from_database(self):
        """Delete retrieval record from the database only."""
        target, arr_values, selected_name = self.get_row()
        if target is None:
            return

        # Confirmation dialog
        retrieval_id = arr_values[ConstantVariables.DICT_FILTER_TABLE["ID"]["index"]]
        confirm = messagebox.askyesno(
            "Confirm Deletion",
            f"Are you sure you want to delete retrieval '{retrieval_id}' from the database?\n\n"
            f"This will remove the database entry only.\n"
            f"Archive files will remain intact and can be re-imported.\n\n"
            f"This action cannot be undone."
        )

        if not confirm:
            return

        # Connect to database and delete record
        db = DBSQLite3(self.path_default)
        db.delete_retrieval_by_date(retrieval_id)
        db.close_DB()
        messagebox.showinfo("Deleted", "Retrieval deleted from database successfully.")

    def delete_from_both(self):
        """Delete retrieval from both database and archive."""
        target, arr_values, selected_name = self.get_row()
        if target is None:
            return

        # Confirmation dialog - more emphatic for complete deletion
        retrieval_id = arr_values[ConstantVariables.DICT_FILTER_TABLE["ID"]["index"]]
        confirm = messagebox.askyesno(
            "Confirm Complete Deletion",
            f"⚠️  WARNING: Complete Deletion  ⚠️\n\n"
            f"Are you sure you want to COMPLETELY DELETE retrieval '{retrieval_id}'?\n\n"
            f"This will permanently remove:\n"
            f"  • All archive files (MCMC chains, plots, pickles)\n"
            f"  • Database entry and metadata\n\n"
            f"This action is IRREVERSIBLE and cannot be undone!\n\n"
            f"Do you want to proceed?"
        )

        if not confirm:
            return

        # Delete from database first
        db = DBSQLite3(self.path_default)
        db.delete_retrieval_by_date(retrieval_id)
        db.close_DB()

        # Then delete from archive
        path_target = str(Path(
            self.path_folder_targets, target, ConstantVariables.RESULTS_FOLDER,
            retrieval_id
        ))
        os.system("rm -rf " + path_target)
        messagebox.showinfo("Deleted", "Retrieval completely deleted from both archive and database.")

    def show_comment(self):
        """Load and display comments for the selected retrieval."""
        target, arr_values, selected_name = self.get_row()
        if target is None:
            return
            
        try:
            # Construct path to retrieval folder
            self.folder_retrieval = str(
                Path(self.path_folder_targets, target, ConstantVariables.RESULTS_FOLDER, selected_name)
            )
            
            # Read general info CSV file
            df_general_info = pd.read_csv(str(Path(self.folder_retrieval, "df_general_info.csv")))
            
        except Exception as e:
            print("Generic error: " + str(e))
            print(traceback.format_exc())
            messagebox.showerror("File not ok", "File not ok")
            return
            
        try:
            # Extract and display comments
            comments = get_csv_value(df_general_info, "comments")
            self.textfield_comments.insert_text(comments)
            
        except Exception as _:
            messagebox.showerror(
                "There are no comments for this retrieval",
                "There are no comments for this retrieval",
            )
            return

    def update_comment(self):
        """Update comments for the selected retrieval."""
        comments = self.textfield_comments.get_text()
        target, arr_values, selected_name = self.get_row()
        if target is None:
            return
            
        try:
            # Construct path to retrieval folder
            self.folder_retrieval = str(
                Path(self.path_folder_targets, target, ConstantVariables.RESULTS_FOLDER, selected_name)
            )
            
            # Read and update general info CSV
            df_general_info = pd.read_csv(str(Path(self.folder_retrieval, "df_general_info.csv")))
            
            # Update comments value in dataframe
            df_general_info.loc[df_general_info['Variable'] == "comments", "Value"] = comments
            
            # Save updated dataframe
            df_general_info.to_csv(str(Path(self.folder_retrieval, "df_general_info.csv")), index=False)
            
        except Exception as e:
            print("Generic error: " + str(e))
            print(traceback.format_exc())
            messagebox.showerror("File not ok", "File not ok")
            return

    def resume_retrieval(self):
        """Resume an interrupted retrieval with a new random seed."""
        target, arr_values, selected_name = self.get_row()
        if target is None:
            return
            
        try:
            # Calculate number of best parameters
            n_best_pars = len(arr_values[1].split(","))
            
            # Construct paths
            self.folder_retrieval = str(
                Path(self.path_folder_targets, target, ConstantVariables.RESULTS_FOLDER, selected_name)
            )
            path_general_info = str(Path(self.folder_retrieval, "df_general_info.csv"))
            path_df_parameters = str(Path(self.folder_retrieval, "df_parameters.csv"))
            
            # Read general info and get current seed
            df_general_info = pd.read_csv(path_general_info)
            last_seed = get_csv_value(df_general_info, "seed")
            
            # Generate new unique seed
            new_seed = last_seed
            while new_seed == last_seed:
                new_seed = randint(5000)
                
            # Update seed in dataframe
            df_general_info.loc[df_general_info['Variable'] == "seed", "Value"] = new_seed
            df_general_info.to_csv(str(Path(self.folder_retrieval, "df_general_info.csv")), index=False)
            
            # Get output path
            path_results = get_csv_value(df_general_info, "path_results")
            path_file_output = str(Path(path_results, "output.txt"))
            
            # Start the main retrieval process
            self.frame_input.frame_input.frame_parameter.panel_start.start_main(
                path_df_parameters, path_general_info, path_file_output, target, selected_name,
                resume="True", end_core=self.entry_end_core.get_value(),
                priority_proc=self.entry_priority_process.get_value(),
                n_best_pars=n_best_pars, checkbox_taskset=self.checkbox_use_taskset.get_value(),
            )
            
            messagebox.showinfo("Resume", f"Retrieval resumed: last seed = {last_seed}, new seed = {new_seed}")
            
        except Exception as e:
            err = str(e) + "\n" + str(traceback.format_exc())
            print(err)
            messagebox.showerror("File not ok", err)
            return

    def display_info_retrieval(self):
        """Display information about the selected retrieval."""
        target, arr_values, selected_name = self.get_row()
        if target is None:
            return
            
        try:
            # Construct path to retrieval folder
            self.folder_retrieval = str(
                Path(self.path_folder_targets, target, ConstantVariables.RESULTS_FOLDER, selected_name)
            )
            
            # Read general info and extract seed
            df_general_info = pd.read_csv(str(Path(self.folder_retrieval, "df_general_info.csv")))
            seed = get_csv_value(df_general_info, "seed")
            
            # Format and display information
            information = f"Seed: {seed}\n"
            self.textfield_information.insert_text(information)
            
        except Exception as e:
            err = str(e) + "\n" + str(traceback.format_exc())
            print(err)
            messagebox.showerror("File not ok", err)
            return

    def get_row(self):
        """
        Get the currently selected row data from the table.
        
        Returns:
            tuple: (target, arr_values, selected_name) or (None, None, None) if no row selected
        """
        try:
            target = self.frame_input.frame_filter_table.frame_filter.dropdown_target.get_value()
            arr_values = self.frame_input.frame_filter_table.frame_table.table.get_arr_values()
            selected_name = arr_values[ConstantVariables.DICT_FILTER_TABLE["ID"]["index"]]
            
        except Exception as _:
            messagebox.showerror("Choose a row", "Choose a row")
            return None, None, None
            
        return target, arr_values, selected_name

    # Legacy method names for backward compatibility
    def delete_1(self):
        """Legacy method name - calls delete_from_archive."""
        return self.delete_from_archive()

    def delete_2(self):
        """Legacy method name - calls delete_from_database."""
        return self.delete_from_database()

    def delete_3(self):
        """Legacy method name - calls delete_from_both."""
        return self.delete_from_both()

    def show_comment_func(self):
        """Legacy method name - calls show_comment."""
        return self.show_comment()

    def update_comment_func(self):
        """Legacy method name - calls update_comment."""
        return self.update_comment()