# radar_data_reader/utils/config_manager.py

"""
Configuration Manager for the application.
Handles loading and saving of application settings to a JSON file.
"""

import json
from pathlib import Path
from typing import Dict, Any, Optional, List

from . import logger
from ..core.export_profiles import ExportProfile, ExportField

log = logger.get_logger(__name__)


class ConfigManager:
    """Manages loading and saving configuration from/to a JSON file."""

    def __init__(self, config_path: Path):
        self.config_path: Path = config_path
        self.config: Dict[str, Any] = {}
        self.export_profiles: List[ExportProfile] = []

    @staticmethod
    def _get_default_config() -> Dict[str, Any]:
        """Provides the default configuration structure for the entire application."""
        default_export_profile = ExportProfile(
            name="Default",
            fields=[
                ExportField(column_name="batch_id", data_path="batch_id"),
                ExportField(
                    column_name="timetag",
                    data_path="main_header.ge_header.signal_descr.ttag",
                ),
            ],
        )

        default_cpp_config = {
            "cpp_executable_path": "C:/path/to/your/g_reconvert.exe",
            "analyze_only": False,
            "no_sign": False,
            "use_fw_header": False,
            "fix_dsp_bug": False,
            "sync_signal_flows": False,
            "extract_sw_only": False,
            "extract_dsp_only": False,
            "stop_on_discontinuity": False,
            "dry_run": False,
            "start_from_stby": False,
            "fix_sata_date": False,
            "examine_data": False,
            "post_process": True,
            "post_process_level": "1",
            "output_format": "",
            "json_config_file": "",
            "max_batches": "",
            "pri_number": "",
            "rbin_number": "",
            "video_out_to_rec": False,
            "video_show": True,
            "video_save": True,
            "video_fix_framerate": False,
            "gps_save_track": True,
            "fix_hr_debug": False,
            "sar_save_only": False,
            "video_add_subtitles": False,
            "verbose": False,
            "debug_messages": False,
            "quiet": False,
            "mask_warnings": False,
            "mask_errors": False,
            "silent_overwrite": True,
            "enable_python_worker_profiling": False,
        }

        segment_g_reconverter_options = default_cpp_config.copy()
        segment_g_reconverter_options.update(
            {
                "post_process": False,
                "video_show": False,
                "video_save": False,
                "gps_save_track": True,
                "no_sign": False,
            }
        )

        default_segment_export_config = {
            "naming_options": {
                "folder_name_template": "{Segment}_{StartBatch}-{EndBatch}",
            },
            "g_reconverter_options": segment_g_reconverter_options,
        }

        return {
            "last_opened_out_file": "",
            "last_opened_rec_file": "",
            "last_out_output_dir": "",
            "last_rec_output_dir": "",
            "last_flight_folder": "",
            "last_flight_workspace_parent_dir": "", 
            "active_out_export_profile_name": "Default",
            "export_profiles": [default_export_profile.to_dict()],
            "cpp_converter_config": default_cpp_config,
            "segment_export_config": default_segment_export_config,
            "segment_processor_config": {
                "last_output_dir": "",
                "create_separate_folders": True,
            },
            "flight_analysis_options": {
                "aggregate_by_scale": True,
                "aggregate_by_waveform": True,
            },
        }

    def load_config(self) -> None:
        log.info(f"Attempting to load configuration from: {self.config_path}")
        if self.config_path.is_file():
            try:
                with open(self.config_path, "r", encoding="utf-8") as f:
                    loaded_data = json.load(f)

                default_conf = self._get_default_config()

                self.config = default_conf
                for key, value in loaded_data.items():
                    if isinstance(value, dict) and key in self.config:
                        self.config[key].update(value)
                        if (
                            key == "segment_export_config"
                            and "g_reconverter_options" in self.config[key]
                        ):
                            main_exe_path = self.config.get(
                                "cpp_converter_config", {}
                            ).get("cpp_executable_path")
                            if main_exe_path:
                                self.config[key]["g_reconverter_options"][
                                    "cpp_executable_path"
                                ] = main_exe_path
                    else:
                        self.config[key] = value

                profiles_data = self.config.get("export_profiles", [])
                self.export_profiles = [
                    ExportProfile.from_dict(p_data) for p_data in profiles_data
                ]

                if not self.export_profiles:
                    self._load_default_profiles()

                log.info(
                    f"Configuration loaded. Found {len(self.export_profiles)} export profiles."
                )

            except (json.JSONDecodeError, IOError, KeyError) as e:
                log.error(f"Failed to load or parse config file: {e}. Using defaults.")
                self.config = self._get_default_config()
                self._load_default_profiles()
        else:
            log.warning("Configuration file not found. Using default settings.")
            self.config = self._get_default_config()
            self._load_default_profiles()

    def _load_default_profiles(self):
        default_conf = self._get_default_config()
        profiles_data = default_conf.get("export_profiles", [])
        self.export_profiles = [
            ExportProfile.from_dict(p_data) for p_data in profiles_data
        ]

    def save_config(self) -> None:
        log.info(f"Saving configuration to: {self.config_path}")
        self.config["export_profiles"] = [
            profile.to_dict() for profile in self.export_profiles
        ]
        try:
            self.config_path.parent.mkdir(parents=True, exist_ok=True)
            with open(self.config_path, "w", encoding="utf-8") as f:
                json.dump(self.config, f, indent=4)
            log.info("Configuration saved successfully.")
        except IOError as e:
            log.error(f"Failed to save configuration file: {e}")

    def get(self, key: str, default: Optional[Any] = None) -> Any:
        return self.config.get(key, default)

    def set(self, key: str, value: Any) -> None:
        self.config[key] = value

    def get_cpp_converter_config(self) -> Dict[str, Any]:
        return self.config.get(
            "cpp_converter_config", self._get_default_config()["cpp_converter_config"]
        )

    def save_cpp_converter_config(self, new_config: Dict[str, Any]):
        self.config["cpp_converter_config"] = new_config
        self.save_config()

    def get_export_profiles(self) -> List[ExportProfile]:
        return self.export_profiles

    def save_export_profiles(self, profiles: List[ExportProfile]):
        self.export_profiles = profiles
        self.save_config()
