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

from __future__ import annotations

from typing import TYPE_CHECKING

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

if TYPE_CHECKING:
    from pytola_sim.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:
            logger.exception("Error closing database connections")

        # Call parent shutdown
        super().quit()

        logger.info("Application controller shutdown completed")
