"""
Frame for managing molecule parameters in the molecules.yaml file.
This module handles the editing and addition of molecules in the
molecules.yaml configuration file.
"""
from pathlib import Path

import yaml
from tkinter import messagebox

from GUIBRUSHR.GUI.LAYOUT.MyPanel import MyPanel
from GUIBRUSHR.GUI.WIDGET.MyButton import MyButton
from GUIBRUSHR.GUI.WIDGET.MyDropDown import MyDropdown
from GUIBRUSHR.GUI.WIDGET.MyTextField import MyTextField
from GUIBRUSHR.General_Constants.Classes.HelpButton import HelpButton


class FrameParams(MyPanel):
    """
    A panel for managing molecule parameters in the molecules.yaml file.

    This class provides functionality to:
    - View existing molecule parameters (name, label)
    - Modify molecule parameters
    - Add new molecules to the configuration
    Note: multi is always set to 0 automatically
    """

    def __init__(self, parent, color, row, column, path_default, **kwargs):
        """Initialize the FrameParams panel with all necessary components."""
        super().__init__(parent, color, row, column, **kwargs)

        # Store instance variables
        self.dropdown_molecule = None
        self.path_default = path_default
        self.molecs_file = str(Path(path_default, "GUIBRUSHR", "Files", "Configuration_Yaml", "molecules.yaml"))
        self.color = color
        self.molecules_dict = {}
        self.molecule_list = []
        self.current_molecule = None

        # Load molecules from molecules.yaml
        self._load_molecules()

        # Initialize panels
        self._init_panels()
        # Initialize controls for editing molecules
        self._init_edit_controls()
        # Initialize controls for adding new molecules
        self._init_add_controls()

    def _init_panels(self):
        """Initialize the main panel columns."""
        self.column1 = MyPanel(self, self.color, 0, 1)
        self.column2 = MyPanel(self, self.color, 0, 2)

    def _init_edit_controls(self):
        """Initialize controls for editing existing molecules."""
        # Help text dictionary
        help_text = {
            "Molecule (dropdown)": "Select an existing molecule from the molecules.yaml file to view and edit its parameters. This dropdown shows all molecules currently defined in the molecules.yaml.",

            "Name": "The internal name identifier for the molecule. This should match the key in the molecules.yaml file and correspond to the molecule name used in petitRADTRANS opacity files.",

            "Label": "LaTeX-formatted label string for display in plots and GUI. Use raw string notation with LaTeX math mode, e.g., r'$log_{10} (vmr\\,H_2O)$' for H₂O volume mixing ratio. Note: multi is always set to 0 automatically."
        }

        # Create help button
        self.help_button_edit = HelpButton(
            self.column1, 0, 0,
            "Molecule Parameters Help",
            help_text,
            columnspan=1
        )
        self.help_button_edit.button.grid(rowspan=3)

        # Molecule dropdown
        molecule_list = list(self.molecules_dict.keys())
        self.dropdown_molecule = MyDropdown(
            self.column1, 0, 1, molecule_list, "Molecule:",
            color=self.color, columnspan=2
        )

        self.dropdown_molecule.set_callback(self._on_molecule_selected)

        # Text fields for molecule parameters
        self.textfield_name = MyTextField(
            self.column1, 1, 1, "", "Name:", width=30, columnspan=2
        )
        self.textfield_label = MyTextField(
            self.column1, 2, 1, "", "Label:", width=30, columnspan=2
        )
        self._on_molecule_selected()

        # Modify button
        self.button_modify = MyButton(
            self.column1, 3, 1, r'Modify Molecule',
            bg="#1e4fda", color_panel=self.color, command=self.modify_molecule
        )

    def _init_add_controls(self):
        """Initialize controls for adding new molecules."""
        # Help text dictionary for adding molecules
        help_text_add = {
            "Molecule Key": "The unique key identifier for the new molecule. This will be used as the dictionary key in molecules.yaml file. Use standard chemical notation (e.g., 'H2O', 'CO2', 'CH4').",

            "Name": "The internal name identifier for the new molecule. Typically matches the key and corresponds to the molecule name in petitRADTRANS opacity files.",

            "Label": "LaTeX-formatted label string for display. Use raw string notation with LaTeX math mode, e.g., r'$log_{10} (vmr\\,H_2O)$'. Escape special characters properly. Note: multi is always set to 0 automatically."
        }

        # Create help button for add panel
        self.help_button_add = HelpButton(
            self.column2, 0, 0,
            "Add New Molecule Help",
            help_text_add,
            columnspan=1
        )
        self.help_button_add.button.grid(rowspan=3)

        # Text fields for new molecule
        self.textfield_new_key = MyTextField(
            self.column2, 1, 1, "", "Molecule Key:", width=30, columnspan=2
        )
        self.textfield_new_name = MyTextField(
            self.column2, 2, 1, "", "Name:", width=30, columnspan=2
        )
        self.textfield_new_label = MyTextField(
            self.column2, 3, 1, "", "Label:", width=30, columnspan=2
        )

        # Add button
        self.button_add = MyButton(
            self.column2, 4, 1, r'Add New Molecule',
            bg="#1e4fda", color_panel=self.color, command=self.add_molecule
        )

    def _load_molecules(self):
        """Load molecules from the molecules.yaml file."""
        try:
            with open(self.molecs_file, 'r') as f:
                # Use safe_load to load the YAML content
                self.molecules_dict = yaml.safe_load(f)

        except Exception as e:
            messagebox.showerror(
                "Error Loading File",
                f"Failed to load molecules.yaml: {str(e)}"
            )
            self.molecules_dict = {}

    def _on_molecule_selected(self):
        """Handle molecule selection from dropdown."""
        selected = self.dropdown_molecule.get_value()
        if selected and selected in self.molecules_dict:
            self.current_molecule = selected
            mol_data = self.molecules_dict[selected]

            # Update text fields with molecule data
            self.textfield_name.insert_text(str(mol_data.get('name', '')))
            self.textfield_label.insert_text(str(mol_data.get('label', '')))

    def modify_molecule(self):
        """Modify the selected molecule's parameters in molecules.yaml."""
        try:
            # Get current selection
            selected = self.dropdown_molecule.get_value()
            if not selected:
                messagebox.showwarning(
                    "No Selection",
                    "Please select a molecule to modify"
                )
                return

            # Get new values from text fields
            new_name = self.textfield_name.get_text()
            new_label = self.textfield_label.get_text()

            # Validate inputs
            if not new_name or not new_label:
                messagebox.showwarning(
                    "Missing Values",
                    "Please fill in all fields"
                )
                return

            # Multi is always set to 0
            new_multi = 0

            # Read the entire YAML file
            with open(self.molecs_file, 'r') as f:
                content = yaml.safe_load(f)

            content[selected] = {
                'name': new_name,
                'multi': new_multi,
                'label': new_label
            }

            # Write back to file, preserving structure
            with open(self.molecs_file, 'w') as f:
                yaml.dump(content, f, default_flow_style=False, allow_unicode=True)

            # Update internal dictionary
            self.molecules_dict[selected] = {
                'name': new_name,
                'multi': new_multi,
                'label': new_label
            }

            messagebox.showinfo(
                "Success",
                f"Molecule '{selected}' updated successfully"
            )

        except Exception as e:
            messagebox.showerror(
                "Error",
                f"Failed to modify molecule: {str(e)}"
            )

    def add_molecule(self):
        """Add a new molecule to the molecules.yaml file."""
        try:
            # Get values from text fields
            new_key = self.textfield_new_key.get_text()
            new_name = self.textfield_new_name.get_text()
            new_label = self.textfield_new_label.get_text()

            # Validate inputs
            if not new_key or not new_name or not new_label:
                messagebox.showwarning(
                    "Missing Values",
                    "Please fill in all fields"
                )
                return

            # Multi is always set to 0
            new_multi = 0

            # Check if molecule already exists
            if new_key in self.molecules_dict:
                messagebox.showwarning(
                    "Duplicate Key",
                    f"Molecule '{new_key}' already exists. Use modify instead."
                )
                return

            # Read the entire YAML file
            with open(self.molecs_file, 'r') as f:
                content = yaml.safe_load(f)

            content[new_key] = {
                'name': new_name,
                'multi': new_multi,
                'label': new_label
            }

            # Write back to file
            with open(self.molecs_file, 'w') as f:
                yaml.dump(content, f, default_flow_style=False, allow_unicode=True)

            # Update internal dictionary
            self.molecules_dict[new_key] = {
                'name': new_name,
                'multi': new_multi,
                'label': new_label
            }

            # Update dropdown with new molecule
            self.molecule_list = list(self.molecules_dict.keys())
            self.modify_list_molecule(self.molecule_list)

            # Clear the add form
            self.textfield_new_key.insert_text("")
            self.textfield_new_name.insert_text("")
            self.textfield_new_label.insert_text("")

            messagebox.showinfo(
                "Success",
                f"Molecule '{new_key}' added successfully"
            )

        except Exception as e:
            messagebox.showerror(
                "Error",
                f"Failed to add molecule: {str(e)}"
            )

    def modify_list_molecule(self, molecule_list):
        """Update the molecule list dropdown with new molecules."""
        self.dropdown_molecule.clean_widget()
        self.dropdown_molecule = MyDropdown(
            self.column1, 0, 1, molecule_list,
            "Molecule:", color=self.color, columnspan=2
        )
        # Re-bind the selection event after recreating dropdown
        self.dropdown_molecule.set_callback(self._on_molecule_selected)
        self.molecule_list = molecule_list