"""Brand configuration loading and management."""

from __future__ import annotations

import json
from pathlib import Path
from typing import Optional

import yaml

from pptx_mcp.models.brand import BrandConfig
from pptx_mcp.brand.defaults import get_preset, executive_default
from pptx_mcp.utils.errors import BrandConfigError
from pptx_mcp.utils.logging import get_logger

logger = get_logger("brand.config")


def load_brand_config(path: str | Path) -> BrandConfig:
    """Load a brand configuration from a JSON or YAML file.

    Args:
        path: Path to the brand config file (.json or .yaml/.yml).

    Returns:
        Parsed BrandConfig instance.

    Raises:
        BrandConfigError: If the file cannot be read or parsed.
    """
    path = Path(path)
    if not path.exists():
        raise BrandConfigError(f"Brand config file not found: {path.name}")

    try:
        raw = path.read_text(encoding="utf-8")
    except OSError:
        raise BrandConfigError(f"Cannot read brand config file: {path.name}")

    try:
        if path.suffix in (".yaml", ".yml"):
            data = yaml.safe_load(raw)
        elif path.suffix == ".json":
            data = json.loads(raw)
        else:
            raise BrandConfigError(
                f"Unsupported config format '{path.suffix}'. Use .json, .yaml, or .yml"
            )
    except (yaml.YAMLError, json.JSONDecodeError) as e:
        raise BrandConfigError(f"Failed to parse brand config: {e}") from e

    if not isinstance(data, dict):
        raise BrandConfigError("Brand config must be a JSON/YAML object at the top level")

    try:
        return BrandConfig.model_validate(data)
    except Exception as e:
        raise BrandConfigError(f"Invalid brand config structure: {e}") from e


def resolve_brand_config(
    path: Optional[str | Path] = None,
    preset: Optional[str] = None,
) -> BrandConfig:
    """Resolve brand configuration from path, preset name, or default.

    Priority:
      1. Explicit file path
      2. Preset name
      3. Executive default

    Args:
        path: Optional path to a brand config file.
        preset: Optional preset name.

    Returns:
        Resolved BrandConfig.
    """
    if path is not None:
        logger.info("Loading brand config from: %s", path)
        return load_brand_config(path)

    if preset is not None:
        logger.info("Using brand preset: %s", preset)
        return get_preset(preset)

    logger.info("Using executive default brand config")
    return executive_default()
