"""
ConfigService - Project Configuration Management

Handles loading, saving, and validating project-specific .dss/config.json files.
Uses Pydantic for schema validation with sensible defaults.
"""

import json
import os
from pathlib import Path
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field
import logging

logger = logging.getLogger(__name__)


# === Configuration Schema ===

class FigmaConfig(BaseModel):
    """Figma integration settings."""
    file_id: Optional[str] = None
    team_id: Optional[str] = None


class TokensConfig(BaseModel):
    """Design token export settings."""
    output_path: str = "./tokens"
    format: str = "css"  # css | scss | json | js


class AIConfig(BaseModel):
    """AI assistant behavior settings."""
    allowed_operations: List[str] = Field(default_factory=lambda: ["read", "write"])
    context_files: List[str] = Field(default_factory=lambda: ["./README.md"])
    max_file_size_kb: int = 500


class DSSConfig(BaseModel):
    """
    Complete DSS project configuration schema.

    Stored in: [project_root]/.dss/config.json
    """
    schema_version: str = "1.0"
    figma: FigmaConfig = Field(default_factory=FigmaConfig)
    tokens: TokensConfig = Field(default_factory=TokensConfig)
    ai: AIConfig = Field(default_factory=AIConfig)

    class Config:
        # Allow extra fields for forward compatibility
        extra = "allow"


# === Config Service ===

class ConfigService:
    """
    Service for managing project configuration files.

    Loads .dss/config.json from project roots, validates against schema,
    and provides defaults when config is missing.
    """

    CONFIG_FILENAME = "config.json"
    DSS_FOLDER = ".dss"

    def __init__(self):
        """Initialize config service."""
        logger.info("ConfigService initialized")

    def get_config_path(self, project_root: str) -> Path:
        """Get path to config file for a project."""
        return Path(project_root) / self.DSS_FOLDER / self.CONFIG_FILENAME

    def get_config(self, project_root: str) -> DSSConfig:
        """
        Load configuration for a project.

        Args:
            project_root: Absolute path to project root directory

        Returns:
            DSSConfig object (defaults if config file missing)
        """
        config_path = self.get_config_path(project_root)

        if config_path.exists():
            try:
                with open(config_path) as f:
                    data = json.load(f)
                    config = DSSConfig(**data)
                    logger.debug(f"Loaded config from {config_path}")
                    return config
            except (json.JSONDecodeError, Exception) as e:
                logger.warning(f"Failed to parse config at {config_path}: {e}")
                # Fall through to return defaults

        logger.debug(f"Using default config for {project_root}")
        return DSSConfig()

    def save_config(self, project_root: str, config: DSSConfig) -> None:
        """
        Save configuration for a project.

        Args:
            project_root: Absolute path to project root directory
            config: DSSConfig object to save
        """
        config_path = self.get_config_path(project_root)

        # Ensure .dss directory exists
        config_path.parent.mkdir(parents=True, exist_ok=True)

        with open(config_path, 'w') as f:
            json.dump(config.dict(), f, indent=2)

        logger.info(f"Saved config to {config_path}")

    def update_config(self, project_root: str, updates: Dict[str, Any]) -> DSSConfig:
        """
        Update specific fields in project config.

        Args:
            project_root: Absolute path to project root directory
            updates: Dictionary of fields to update

        Returns:
            Updated DSSConfig object
        """
        config = self.get_config(project_root)

        # Deep merge updates
        config_dict = config.dict()
        for key, value in updates.items():
            if isinstance(value, dict) and isinstance(config_dict.get(key), dict):
                config_dict[key].update(value)
            else:
                config_dict[key] = value

        new_config = DSSConfig(**config_dict)
        self.save_config(project_root, new_config)
        return new_config

    def init_config(self, project_root: str) -> DSSConfig:
        """
        Initialize config file for a new project.

        Creates .dss/ folder and config.json with defaults if not exists.

        Args:
            project_root: Absolute path to project root directory

        Returns:
            DSSConfig object (new or existing)
        """
        config_path = self.get_config_path(project_root)

        if config_path.exists():
            logger.debug(f"Config already exists at {config_path}")
            return self.get_config(project_root)

        config = DSSConfig()
        self.save_config(project_root, config)
        logger.info(f"Initialized new config at {config_path}")
        return config

    def config_exists(self, project_root: str) -> bool:
        """Check if config file exists for a project."""
        return self.get_config_path(project_root).exists()
