"""Application main controller for LSCSIM."""

from __future__ import annotations

from typing import TYPE_CHECKING

from pytola.simulation.lscsim.analysismodel import AnalysisComponent
from pytola.simulation.lscsim.components.filemodel import FileModelComponent
from pytola.simulation.lscsim.components.helpmodel import HelpComponent
from pytola.simulation.lscsim.components.modelingmodel import ModelingComponent
from pytola.simulation.lscsim.components.productdb import ProductDatabaseComponent
from pytola.simulation.lscsim.components.setmodel import SettingsComponent
from pytola.simulation.lscsim.components.simdb import SimulationDatabaseComponent
from pytola.simulation.lscsim.core.enhanced.main_ctrl import EnhancedMainController
from pytola.simulation.lscsim.services.database_service import DatabaseService
from pytola.simulation.lscsim.utils.logger import get_logger

if TYPE_CHECKING:
    from pytola.simulation.lscsim.interfaces.icomponent import IComponent

logger = get_logger(__name__)


class ApplicationController(EnhancedMainController):
    """Application main controller with all components registered."""

    def __init__(self) -> None:
        # Initialize database service first
        self._database_service = DatabaseService()
        super().__init__()

    def _register_all_components(self) -> None:
        """Register all application components."""
        logger.info("Registering application components")

        # Register core business components
        self._register_business_components()

        # Register database components
        self._register_database_components()

        # Register utility components
        self._register_utility_components()

        logger.info("All application components registered successfully")

    def _register_business_components(self) -> None:
        """Register core business components."""
        # File model component
        file_model = FileModelComponent()
        if self.register_component(file_model):
            file_commands = [
                "File.NewProject",
                "File.OpenProject",
                "File.SaveProject",
                "File.ImportCoordinates",
                "File.SelectTargetPlate",
                "File.SelectMaterial",
                "File.SetExplosionHeight",
                "File.SetDetonationPoint",
                "File.SelectTemplate",
            ]
            self.register_command(file_model, file_commands)

        # Modeling component
        modeling = ModelingComponent()
        if self.register_component(modeling):
            modeling_commands = [
                "Modeling.CreateGeometry",
                "Modeling.BooleanOperation",
                "Modeling.SetMeshParameters",
                "Modeling.GenerateMesh",
                "Modeling.RefineMesh",
                "Modeling.OptimizeMesh",
                "Modeling.ApplyBoundaryConditions",
                "Modeling.ApplyLoads",
                "Modeling.AssignMaterial",
                "Modeling.ValidateModel",
                "Modeling.PreviewModel",
            ]
            self.register_command(modeling, modeling_commands)

        # Analysis component
        analysis = AnalysisComponent()
        if self.register_component(analysis):
            analysis_commands = [
                "Analysis.SetupCalculation",
                "Analysis.StartCalculation",
                "Analysis.PauseCalculation",
                "Analysis.StopCalculation",
                "Analysis.GetResults",
                "Analysis.ExportResults",
                "Analysis.EnvelopeAnalysis",
            ]
            self.register_command(analysis, analysis_commands)

    def _register_database_components(self) -> None:
        """Register database components."""
        # Product database component
        product_db = ProductDatabaseComponent()
        if self.register_component(product_db):
            product_commands = [
                "ProductDB.LoadProducts",
                "ProductDB.SaveProducts",
                "ProductDB.AddProduct",
                "ProductDB.UpdateProduct",
                "ProductDB.DeleteProduct",
                "ProductDB.SearchProducts",
                "ProductDB.GetProductStructure",
                "ProductDB.ExportProductData",
            ]
            self.register_command(product_db, product_commands)

        # Simulation database component
        sim_db = SimulationDatabaseComponent()
        if self.register_component(sim_db):
            sim_commands = [
                "SimDB.LoadMaterials",
                "SimDB.AddMaterial",
                "SimDB.UpdateMaterial",
                "SimDB.DeleteMaterial",
                "SimDB.SearchMaterials",
                "SimDB.LoadTargetPlates",
                "SimDB.AddTargetPlate",
                "SimDB.UpdateTargetPlate",
                "SimDB.DeleteTargetPlate",
                "SimDB.SearchTargetPlates",
                "SimDB.LoadTemplates",
                "SimDB.AddTemplate",
                "SimDB.UpdateTemplate",
                "SimDB.DeleteTemplate",
                "SimDB.SearchTemplates",
                "SimDB.ExportLibrary",
            ]
            self.register_command(sim_db, sim_commands)

    def _register_utility_components(self) -> None:
        """Register utility components."""
        # Settings component
        settings = SettingsComponent()
        if self.register_component(settings):
            settings_commands = [
                "Settings.LoadSettings",
                "Settings.SaveSettings",
                "Settings.UpdateSetting",
                "Settings.ResetSettings",
                "Settings.LoadUserProfiles",
                "Settings.AddUserProfile",
                "Settings.UpdateUserProfile",
                "Settings.DeleteUserProfile",
                "Settings.SetActiveUser",
                "Settings.ValidatePaths",
                "Settings.TestConnections",
                "Settings.ExportConfiguration",
            ]
            self.register_command(settings, settings_commands)

        # Help component
        help_comp = HelpComponent()
        if self.register_component(help_comp):
            help_commands = [
                "Help.ShowDocumentation",
                "Help.SearchDocumentation",
                "Help.GetTOC",
                "Help.ShowTutorial",
                "Help.ListTutorials",
                "Help.GetTutorialProgress",
                "Help.MarkTutorialComplete",
                "Help.ShowFAQ",
                "Help.SearchFAQ",
                "Help.SubmitQuestion",
                "Help.ShowAbout",
                "Help.CheckUpdates",
                "Help.ShowSystemInfo",
            ]
            self.register_command(help_comp, help_commands)

    def get_all_registered_commands(self) -> list[str]:
        """Get list of all registered commands."""
        return list(self._commands.keys())

    def get_component_for_command(self, command_id: str) -> IComponent | None:
        """Get the component responsible for a command."""
        return self._commands.get(command_id)

    def shutdown(self) -> None:
        """Shutdown the application controller gracefully."""
        logger.info("Shutting down application controller")

        # Shutdown database service
        try:
            # Close database connection if it exists
            if hasattr(self._database_service, "connection") and self._database_service.connection:
                self._database_service.connection.close()
                logger.info("Database connection closed")
        except Exception as e:
            logger.exception(f"Error closing database connections: {e}")

        # Call parent shutdown
        super().quit()

        logger.info("Application controller shutdown completed")
