"""Configuration-backed product profile for a reusable agent console."""

from __future__ import annotations

from dataclasses import dataclass
import json
import os
from pathlib import Path
from typing import Any, Mapping


class AppProfileError(RuntimeError):
    """Safe error for an invalid product profile."""


@dataclass(frozen=True)
class AppProfile:
    product_name: str
    short_name: str
    page_title: str
    page_icon: str
    header_title: str
    header_description: str
    login_kicker: str
    login_title: str
    login_description: str
    login_footer: str
    primary_color: str
    text_color: str
    muted_color: str
    border_color: str


_ENV_FIELD_NAMES = {
    "product_name": "AGENT_CONSOLE_NAME",
    "short_name": "AGENT_CONSOLE_SHORT_NAME",
    "page_title": "AGENT_CONSOLE_PAGE_TITLE",
    "page_icon": "AGENT_CONSOLE_PAGE_ICON",
    "header_title": "AGENT_CONSOLE_HEADER_TITLE",
    "header_description": "AGENT_CONSOLE_HEADER_DESCRIPTION",
    "login_kicker": "AGENT_CONSOLE_LOGIN_KICKER",
    "login_title": "AGENT_CONSOLE_LOGIN_TITLE",
    "login_description": "AGENT_CONSOLE_LOGIN_DESCRIPTION",
    "login_footer": "AGENT_CONSOLE_LOGIN_FOOTER",
    "primary_color": "AGENT_CONSOLE_PRIMARY_COLOR",
    "text_color": "AGENT_CONSOLE_TEXT_COLOR",
    "muted_color": "AGENT_CONSOLE_MUTED_COLOR",
    "border_color": "AGENT_CONSOLE_BORDER_COLOR",
}


def _string(section: Mapping[str, Any], key: str, fallback: str = "") -> str:
    return str(section.get(key) or fallback).strip()


def resolve_profile_path(default_path: Path) -> Path:
    configured = os.environ.get("AGENT_CONSOLE_PROFILE_PATH", "").strip()
    if not configured:
        return default_path
    path = Path(configured).expanduser()
    return path if path.is_absolute() else default_path.parent / path


def _dotenv_value(name: str, path: Path | None) -> str:
    """Read one simple KEY=value runtime setting without importing a dotenv lib."""

    if path is None:
        return ""
    try:
        lines = path.read_text(encoding="utf-8").splitlines()
    except (OSError, UnicodeError):
        return ""
    prefix = f"{name}="
    for line in lines:
        stripped = line.strip()
        if stripped.startswith(prefix):
            return stripped[len(prefix) :].strip().strip('"').strip("'")
    return ""


def _apply_environment_overrides(profile: AppProfile, env_file: Path | None) -> AppProfile:
    """Apply deployment-specific presentation values without a code change."""

    values = {
        field_name: (
            os.environ.get(env_name, "").strip()
            or _dotenv_value(env_name, env_file)
            or getattr(profile, field_name)
        )
        for field_name, env_name in _ENV_FIELD_NAMES.items()
    }
    return AppProfile(**values)


def load_app_profile(default_path: Path, env_file: Path | None = None) -> AppProfile:
    """Load the selectable product skin without coupling it to a PoC name."""

    path = resolve_profile_path(default_path)
    try:
        payload: Any = json.loads(path.read_text(encoding="utf-8"))
    except (OSError, UnicodeError, ValueError):
        raise AppProfileError(f"애플리케이션 프로필을 읽지 못했습니다: {path}") from None
    if not isinstance(payload, Mapping):
        raise AppProfileError("애플리케이션 프로필 형식이 올바르지 않습니다.")
    product = payload.get("product")
    theme = payload.get("theme")
    if not isinstance(product, Mapping) or not isinstance(theme, Mapping):
        raise AppProfileError("애플리케이션 프로필에 product와 theme 객체가 필요합니다.")

    profile = _apply_environment_overrides(AppProfile(
        product_name=_string(product, "name"),
        short_name=_string(product, "short_name"),
        page_title=_string(product, "page_title"),
        page_icon=_string(product, "page_icon", "🤖"),
        header_title=_string(product, "header_title"),
        header_description=_string(product, "header_description"),
        login_kicker=_string(product, "login_kicker"),
        login_title=_string(product, "login_title"),
        login_description=_string(product, "login_description"),
        login_footer=_string(product, "login_footer"),
        primary_color=_string(theme, "primary_color"),
        text_color=_string(theme, "text_color"),
        muted_color=_string(theme, "muted_color"),
        border_color=_string(theme, "border_color"),
    ), env_file)
    required = (
        profile.product_name,
        profile.short_name,
        profile.page_title,
        profile.header_title,
        profile.login_title,
        profile.primary_color,
        profile.text_color,
        profile.muted_color,
        profile.border_color,
    )
    if not all(required):
        raise AppProfileError("애플리케이션 프로필의 필수 표시값 또는 색상이 비어 있습니다.")
    return profile
