# FlightMonitor/data/area_profile_manager.py
"""
Manages loading, saving, and handling of geographic area profiles.
"""
import json
import os
from typing import Dict, Optional, List

from flightmonitor.utils.logger import get_logger
from flightmonitor.data import config as app_config

module_logger = get_logger(__name__)

PROFILE_FILENAME = "area_profiles.json"
DEFAULT_PROFILE_NAME = "Default Zone"

class AreaProfileManager:
    """
    Handles reading from and writing to the area profiles JSON file.
    """
    def __init__(self, profiles_directory: str = "config"):
        """
        Initializes the AreaProfileManager.

        Args:
            profiles_directory: The directory where the profiles file will be stored.
        """
        self.profiles_path = os.path.join(os.path.abspath(profiles_directory), PROFILE_FILENAME)
        self._profiles: Dict[str, Dict[str, float]] = {}
        self._load_profiles()

    def _create_default_profile(self) -> Dict[str, float]:
        """Creates the default profile from the application config."""
        return {
            "lat_min": app_config.DEFAULT_BBOX_LAT_MIN,
            "lon_min": app_config.DEFAULT_BBOX_LON_MIN,
            "lat_max": app_config.DEFAULT_BBOX_LAT_MAX,
            "lon_max": app_config.DEFAULT_BBOX_LON_MAX,
        }

    def _load_profiles(self):
        """Loads profiles from the JSON file and ensures the default profile exists."""
        # Start with the mandatory default profile
        self._profiles = {DEFAULT_PROFILE_NAME: self._create_default_profile()}
        
        if os.path.exists(self.profiles_path):
            try:
                with open(self.profiles_path, "r") as f:
                    user_profiles = json.load(f)
                    if isinstance(user_profiles, dict):
                        # Merge user profiles, default profile cannot be overwritten
                        for name, data in user_profiles.items():
                            if name != DEFAULT_PROFILE_NAME:
                                self._profiles[name] = data
                    module_logger.info(f"Loaded {len(user_profiles)} user profiles from {self.profiles_path}")
            except (json.JSONDecodeError, IOError) as e:
                module_logger.error(f"Error loading profiles from {self.profiles_path}: {e}")
        else:
            module_logger.info("Area profiles file not found. Starting with default profile.")
            # We can optionally save the default profile to create the file on first run
            self._save_profiles()

    def _save_profiles(self):
        """Saves the current user-defined profiles to the JSON file."""
        # Ensure the directory exists
        try:
            os.makedirs(os.path.dirname(self.profiles_path), exist_ok=True)
        except OSError as e:
            module_logger.error(f"Could not create directory for profiles file: {e}")
            return

        # Prepare user-defined profiles for saving (exclude the default)
        profiles_to_save = {
            name: data for name, data in self._profiles.items() if name != DEFAULT_PROFILE_NAME
        }

        try:
            with open(self.profiles_path, "w") as f:
                json.dump(profiles_to_save, f, indent=4)
            module_logger.info(f"Successfully saved {len(profiles_to_save)} profiles to {self.profiles_path}")
        except IOError as e:
            module_logger.error(f"Error saving profiles to {self.profiles_path}: {e}")

    def get_profile_names(self) -> List[str]:
        """Returns a sorted list of all available profile names."""
        return sorted(self._profiles.keys())

    def get_profile_data(self, name: str) -> Optional[Dict[str, float]]:
        """Returns the BBox data for a given profile name."""
        return self._profiles.get(name)

    def save_profile(self, name: str, data: Dict[str, float]) -> bool:
        """
        Saves a new or updated profile. Returns False if name is invalid or default.
        """
        if not name or name == DEFAULT_PROFILE_NAME:
            module_logger.warning(f"Attempt to save invalid or default profile name: '{name}'")
            return False
        
        self._profiles[name] = data
        self._save_profiles()
        return True

    def delete_profile(self, name: str) -> bool:
        """Deletes a profile. Returns False if the profile is default or not found."""
        if name == DEFAULT_PROFILE_NAME:
            module_logger.warning("Cannot delete the default profile.")
            return False
        if name in self._profiles:
            del self._profiles[name]
            self._save_profiles()
            return True
        module_logger.warning(f"Profile '{name}' not found for deletion.")
        return False