"""Product configuration endpoints."""

import ipaddress
from typing import Any, Dict, List

from fastapi import APIRouter, Depends
from pydantic import BaseModel, Field, field_validator, model_validator

from ..database import get_session
from ..models import AdminConfig
from ..sast_defaults import DEFAULT_TIER_PROFILES, TIER_CONFIG_KEY, load_tier_profiles
from ..security import require_roles
from ..utils import log_action

router = APIRouter()

I18N_CONFIG_KEY = "i18n_settings"
SECURITY_CONFIG_KEY = "security_restrictions"


def _upsert_config(session, key: str, value: Dict[str, Any]) -> AdminConfig:
    config = session.query(AdminConfig).filter(AdminConfig.key == key).first()
    if config:
        config.value = value
    else:
        config = AdminConfig(key=key, value=value)
        session.add(config)
    return config


class I18NConfig(BaseModel):
    default_locale: str = Field(default="en")
    locales: List[str] = Field(default_factory=lambda: ["en"])
    translations: Dict[str, Dict[str, str]] = Field(default_factory=dict)

    @model_validator(mode="after")
    def ensure_default_locale_present(self):
        if self.default_locale not in self.locales:
            raise ValueError("default_locale must be present in locales")
        return self


class SecurityConfig(BaseModel):
    allowed_ips: List[str] = Field(default_factory=list)
    webhook_targets: Dict[str, str] = Field(default_factory=dict)

    @field_validator("allowed_ips")
    @classmethod
    def validate_ips(cls, values: List[str]):
        for value in values:
            try:
                ipaddress.ip_network(value, strict=False)
            except ValueError as exc:
                raise ValueError(f"Adresse IP invalide: {value}") from exc
        return values

    @field_validator("webhook_targets")
    @classmethod
    def validate_webhooks(cls, value: Dict[str, str]):
        for name, url in value.items():
            if not url.startswith("https://"):
                raise ValueError(f"Webhook {name} doit être en HTTPS")
        return value


@router.get("/")
def list_configs(session=Depends(get_session), _admin=Depends(require_roles("super-admin"))):
    configs = session.query(AdminConfig).all()
    return {item.key: item.value for item in configs}


@router.get("/i18n", response_model=I18NConfig)
def get_i18n_config(session=Depends(get_session), _admin=Depends(require_roles("super-admin", "analyst"))):
    config = session.query(AdminConfig).filter(AdminConfig.key == I18N_CONFIG_KEY).first()
    if not config or not config.value:
        return I18NConfig()
    return I18NConfig(**config.value)


@router.put("/i18n", response_model=I18NConfig)
def set_i18n_config(payload: I18NConfig, session=Depends(get_session), _admin=Depends(require_roles("super-admin"))):
    data = payload.model_dump()
    _upsert_config(session, I18N_CONFIG_KEY, data)
    log_action(session, _admin.email, "config_i18n_updated", metadata=data)
    session.commit()
    return payload


@router.get("/security", response_model=SecurityConfig)
def get_security_config(session=Depends(get_session), _admin=Depends(require_roles("super-admin"))):
    config = session.query(AdminConfig).filter(AdminConfig.key == SECURITY_CONFIG_KEY).first()
    if not config or not config.value:
        return SecurityConfig()
    return SecurityConfig(**config.value)


@router.put("/security", response_model=SecurityConfig)
def set_security_config(payload: SecurityConfig, session=Depends(get_session), _admin=Depends(require_roles("super-admin"))):
    data = payload.model_dump()
    _upsert_config(session, SECURITY_CONFIG_KEY, data)
    log_action(session, _admin.email, "config_security_updated", metadata=data)
    session.commit()
    return payload


class TierProfileConfig(BaseModel):
    label: str = Field(default="")
    max_domains: int = Field(default=3)
    max_users: int = Field(default=1)
    allow_source_scan: bool = Field(default=False)
    max_source_files: int = Field(default=0)
    max_source_size_mb: int = Field(default=0)
    advanced_rules: bool = Field(default=False)
    allow_invasive_tests: bool = Field(default=False)
    allow_html_export: bool = Field(default=False)
    allow_multi_user: bool = Field(default=False)
    allow_api_access: bool = Field(default=False)


TierProfilesResponse = Dict[str, TierProfileConfig]


@router.get("/tiers", response_model=TierProfilesResponse)
def get_tier_profiles(session=Depends(get_session), _admin=Depends(require_roles("super-admin", "analyst"))):
    profiles = load_tier_profiles(session)
    # Ensure deterministic ordering
    ordered = {key: TierProfileConfig(**value) for key, value in profiles.items()}
    return ordered


@router.put("/tiers", response_model=TierProfilesResponse)
def set_tier_profiles(
    payload: TierProfilesResponse,
    session=Depends(get_session),
    _admin=Depends(require_roles("super-admin")),
):
    normalized = {
        key.upper(): value.model_dump()
        for key, value in payload.items()
    }
    if not normalized:
        normalized = DEFAULT_TIER_PROFILES
    _upsert_config(session, TIER_CONFIG_KEY, normalized)
    log_action(session, _admin.email, "config_tiers_updated", metadata=normalized)
    session.commit()
    profiles = load_tier_profiles(session)
    return {key: TierProfileConfig(**value) for key, value in profiles.items()}


@router.put("/{key}")
def set_config(key: str, payload: Dict, session=Depends(get_session), _admin=Depends(require_roles("super-admin"))):
    config = _upsert_config(session, key, payload)
    log_action(session, _admin.email, "config_updated", target=key, metadata=payload)
    session.commit()
    return {"key": key, "value": payload}
