"""Style configuration endpoints."""

import json
import logging
import os
import uuid

from fastapi import APIRouter

from src.config.settings import REDIS_ENABLED
from src.models.schemas import ResponseModel
from src.services.cache_service import get_cache_service
from src.utils.errors import AppException, ErrorCode, ResourceNotFoundException, BusinessException

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


@router.get("/config/styles", response_model=ResponseModel)
async def get_styles():
    """Get all style configurations (cached for 5 minutes)."""
    cache_key = "config:styles"

    if REDIS_ENABLED:
        cache = get_cache_service()
        cached_styles = await cache.get(cache_key)
        if cached_styles is not None:
            return ResponseModel(data=cached_styles)

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

        result = {"styles": []}
        if os.path.exists(styles_path):
            with open(styles_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
                result = {"styles": data.get("styles", [])}

        if REDIS_ENABLED:
            cache = get_cache_service()
            await cache.set(cache_key, result, ttl=300)

        return ResponseModel(data=result)
    except Exception as e:
        logger.error(f"Failed to load styles: {e}")
        return ResponseModel(data={"styles": []})


@router.post("/config/styles", response_model=ResponseModel)
async def create_style(style: dict):
    """Create a new style configuration."""
    try:
        src_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
        styles_path = os.path.join(src_dir, "config", "styles.json")

        if not os.path.exists(styles_path):
            data = {"styles": []}
        else:
            with open(styles_path, 'r', encoding='utf-8') as f:
                data = json.load(f)

        if 'id' not in style or not style['id']:
            style['id'] = str(uuid.uuid4())

        data["styles"].append(style)

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

        if REDIS_ENABLED:
            cache = get_cache_service()
            await cache.delete("config:styles")

        return ResponseModel(data=style)
    except Exception as e:
        logger.error(f"Failed to create style: {e}")
        raise AppException(
            message=str(e),
            code=ErrorCode.INTERNAL_ERROR,
            status_code=500
        )


@router.put("/config/styles/{style_id}", response_model=ResponseModel)
async def update_style(style_id: str, style: dict):
    """Update an existing style configuration."""
    try:
        src_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
        styles_path = os.path.join(src_dir, "config", "styles.json")

        if not os.path.exists(styles_path):
            raise AppException(
                message="Styles configuration not found",
                code=ErrorCode.NOT_FOUND,
                status_code=404
            )

        with open(styles_path, 'r', encoding='utf-8') as f:
            data = json.load(f)

        styles = data.get("styles", [])
        updated = False
        for i, s in enumerate(styles):
            if s.get('id') == style_id:
                styles[i] = {**s, **style, "id": style_id}
                updated = True
                break

        if not updated:
            raise AppException(
                message="Style not found",
                code=ErrorCode.NOT_FOUND,
                status_code=404
            )

        data["styles"] = styles
        with open(styles_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)

        if REDIS_ENABLED:
            cache = get_cache_service()
            await cache.delete("config:styles")

        return ResponseModel(data=styles[i])
    except AppException:
        raise
    except Exception as e:
        logger.error(f"Failed to update style: {e}")
        raise AppException(
            message=str(e),
            code=ErrorCode.INTERNAL_ERROR,
            status_code=500
        )


@router.delete("/config/styles/{style_id}", response_model=ResponseModel)
async def delete_style(style_id: str):
    """Delete a style configuration."""
    try:
        src_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
        styles_path = os.path.join(src_dir, "config", "styles.json")

        if not os.path.exists(styles_path):
            raise ResourceNotFoundException("styles configuration", "styles.json")

        with open(styles_path, 'r', encoding='utf-8') as f:
            data = json.load(f)

        styles = data.get("styles", [])
        initial_len = len(styles)
        styles = [s for s in styles if s.get('id') != style_id]

        if len(styles) == initial_len:
            raise ResourceNotFoundException("style", style_id)

        data["styles"] = styles
        with open(styles_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)

        if REDIS_ENABLED:
            cache = get_cache_service()
            await cache.delete("config:styles")

        return ResponseModel(data={"status": "success"})
    except ResourceNotFoundException:
        raise
    except Exception as e:
        logger.error(f"Failed to delete style: {e}", exc_info=True)
        raise BusinessException(
            ErrorCode.UNKNOWN_ERROR,
            "Failed to delete style",
            {"style_id": style_id, "reason": str(e)}
        )


@router.get("/config/generation-options", response_model=ResponseModel)
async def get_generation_options():
    """Get generation options (cached for 5 minutes)."""
    cache_key = "config:generation_options"

    if REDIS_ENABLED:
        cache = get_cache_service()
        cached_options = await cache.get(cache_key)
        if cached_options is not None:
            return ResponseModel(data=cached_options)

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

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

        if REDIS_ENABLED:
            cache = get_cache_service()
            await cache.set(cache_key, result, ttl=300)

        return ResponseModel(data=result)
    except Exception as e:
        logger.error(f"Failed to load generation options: {e}")
        raise AppException(
            message=str(e),
            code=ErrorCode.INTERNAL_ERROR,
            status_code=500
        )
