"""System configuration endpoints."""

import json
import logging
import os
from typing import Optional, Dict, Any

from fastapi import APIRouter
from pydantic import BaseModel, Field, ConfigDict

from src.config.settings import REDIS_ENABLED
from src.models.schemas import ResponseModel
from src.services.cache_service import get_cache_service
from src.services.provider.registry import ModelRegistry, ModelType
from src.utils.errors import BusinessException, ErrorCode

logger = logging.getLogger(__name__)
router = APIRouter()


class SystemConfig(BaseModel):
    """System configuration model."""
    default_image_model: Optional[str] = None
    default_video_model: Optional[str] = None
    default_audio_model: Optional[str] = None
    default_llm_model: Optional[str] = None
    default_style: Optional[str] = None
    default_resolution: Optional[str] = None
    default_ratio: Optional[str] = None

    model_config = ConfigDict(extra="allow")


@router.get("/config/system", response_model=ResponseModel)
async def get_system_config():
    """Get system configuration (cached for 5 minutes).

    Raises:
        BusinessException: Failed to load system config
    """
    cache_key = "config:system"

    # Try cache first
    if REDIS_ENABLED:
        cache = get_cache_service()
        cached_config = await cache.get(cache_key)
        if cached_config is not None:
            return ResponseModel(data=cached_config)

    try:
        src_dir = os.path.dirname(os.path.dirname(__file__))
        config_path = os.path.join(src_dir, "config", "user_config.json")

        config_data = {}
        if os.path.exists(config_path):
            with open(config_path, 'r', encoding='utf-8') as f:
                config_data = json.load(f)

        # Cache result for 5 minutes
        if REDIS_ENABLED:
            cache = get_cache_service()
            await cache.set(cache_key, config_data, ttl=300)

        return ResponseModel(data=config_data)
    except Exception as e:
        logger.error(f"Failed to load system config: {e}", exc_info=True)
        raise BusinessException(
            ErrorCode.UNKNOWN_ERROR,
            "Failed to load system configuration",
            {"reason": str(e)}
        )


@router.post("/config/system", response_model=ResponseModel)
async def update_system_config(config: SystemConfig):
    """Update system configuration.

    Raises:
        BusinessException: Failed to update system config
    """
    try:
        src_dir = os.path.dirname(os.path.dirname(__file__))
        config_path = os.path.join(src_dir, "config", "user_config.json")

        # Load existing to merge
        existing_data = {}
        if os.path.exists(config_path):
            with open(config_path, 'r', encoding='utf-8') as f:
                try:
                    existing_data = json.load(f)
                except json.JSONDecodeError as e:
                    logger.warning("Failed to parse existing config %s: %s", config_path, e)

        new_data = config.model_dump(exclude_unset=True)
        merged_data = {**existing_data, **new_data}

        with open(config_path, 'w', encoding='utf-8') as f:
            json.dump(merged_data, f, indent=2, ensure_ascii=False)

        # Update default models in registry if changed
        config_key_to_type = {
            'defaultImageModel': ModelType.IMAGE,
            'defaultVideoModel': ModelType.VIDEO,
            'defaultAudioModel': ModelType.AUDIO,
            'defaultLyricsModel': ModelType.LYRICS,
            'defaultMusicModel': ModelType.MUSIC,
            'defaultLLMModel': ModelType.LLM
        }

        for config_key, model_type in config_key_to_type.items():
            if config_key in new_data:
                model_id = new_data[config_key]
                if model_id:
                    ModelRegistry.set_default_by_id(model_type, model_id)
                    logger.info(f"Updated default {model_type.value} model to: {model_id}")

        # Invalidate all related caches
        if REDIS_ENABLED:
            cache = get_cache_service()
            await cache.delete("config:system")
            await cache.delete("config:models")
            await cache.delete("config:defaults")

        return ResponseModel(data=merged_data)
    except Exception as e:
        logger.error(f"Failed to update system config: {e}", exc_info=True)
        raise BusinessException(
            ErrorCode.UNKNOWN_ERROR,
            "Failed to update system configuration",
            {"reason": str(e)}
        )
