"""Cliente FOSSBilling Admin API."""

from __future__ import annotations

import os
import secrets
from typing import Any

import httpx

from app.vm123.role_map import FOSS_GROUP_BY_ROLE

FOSS_BASE = os.getenv("FOSSBILLING_URL", "https://financeiro.ligbox.com.br").rstrip("/")
FOSS_ADMIN_USER = os.getenv("FOSS_ADMIN_USER", "admin")
FOSS_ADMIN_API_KEY = os.getenv("FOSS_ADMIN_API_KEY", os.getenv("FOSS_API_KEY", ""))
FOSS_PUBLIC_ADMIN = os.getenv("FOSS_PUBLIC_ADMIN_URL", f"{FOSS_BASE}/admin")


class FossConfigError(RuntimeError):
    pass


def _configured() -> bool:
    return bool(FOSS_ADMIN_API_KEY)


def _auth():
    if not _configured():
        raise FossConfigError("FOSS_ADMIN_API_KEY não configurado no Desk")
    return (FOSS_ADMIN_USER, FOSS_ADMIN_API_KEY)


def _post(path: str, payload: dict) -> dict[str, Any]:
    url = f"{FOSS_BASE}/api/admin/{path.lstrip('/')}"
    with httpx.Client(timeout=20.0) as client:
        res = client.post(url, json=payload, auth=_auth())
    if res.status_code >= 400:
        raise RuntimeError(f"FOSS {path} HTTP {res.status_code}: {res.text[:300]}")
    try:
        return res.json()
    except Exception:
        return {"raw": res.text}


def _extract_id(data: dict[str, Any]) -> int | str | None:
    if data.get("id") is not None:
        return data["id"]
    result = data.get("result")
    if isinstance(result, dict) and result.get("id") is not None:
        return result["id"]
    if result is not None and not isinstance(result, dict):
        return result
    return None


def _list_items(data: dict[str, Any]) -> list[dict[str, Any]]:
    result = data.get("result")
    if isinstance(result, dict) and isinstance(result.get("list"), list):
        return result["list"]
    if isinstance(data.get("list"), list):
        return data["list"]
    return []


def find_client_by_email(email: str) -> dict[str, Any] | None:
    data = _post("client/get_list", {"per_page": 50, "search": email.strip()})
    items = _list_items(data)
    if not items:
        return None
    needle = email.strip().lower()
    for item in items:
        if str(item.get("email", "")).lower() == needle:
            return item
    return items[0] if items else None


def find_client_by_domain(domain: str) -> dict[str, Any] | None:
    dom = domain.strip().lower()
    data = _post("client/get_list", {"per_page": 100})
    items = _list_items(data)
    for item in items:
        for field in ("company", "company_vat", "email"):
            val = str(item.get(field, "")).lower()
            if dom in val:
                return item
    return None


def find_product_by_slug(slug: str) -> dict[str, Any] | None:
    needle = slug.strip().lower()
    data = _post("product/get_list", {"per_page": 100})
    for item in _list_items(data):
        if str(item.get("slug", "")).lower() == needle:
            return item
        title_slug = str(item.get("title", "")).lower().replace(" ", "-")
        if title_slug == needle:
            return item
    return None


def create_client(*, mapped: dict[str, Any], password: str | None = None) -> dict[str, Any]:
    """Cria cliente FOSS — idempotente por email (Spec 043 §4.1)."""
    email = str(mapped.get("email") or "").strip().lower()
    if not email:
        raise ValueError("email obrigatório para FOSS client")
    existing = find_client_by_email(email)
    if existing:
        cid = existing.get("id")
        return {
            "client_id": cid,
            "email": email,
            "created": False,
            "reused": True,
        }
    pwd = password or secrets.token_urlsafe(14)
    payload: dict[str, Any] = {
        "email": email,
        "first_name": mapped.get("first_name") or "",
        "last_name": mapped.get("last_name") or "",
        "company": mapped.get("company") or "",
        "company_vat": mapped.get("company_vat") or "",
        "phone": mapped.get("phone") or "",
        "address_1": mapped.get("address_1") or "",
        "city": mapped.get("city") or "",
        "state": mapped.get("state") or "",
        "postcode": mapped.get("postcode") or "",
        "country": mapped.get("country") or "BR",
        "currency": mapped.get("currency") or "BRL",
        "status": mapped.get("status") or "active",
        "password": pwd,
        "password_confirm": pwd,
    }
    result = _post("client/create", payload)
    cid = _extract_id(result)
    return {
        "client_id": cid,
        "email": email,
        "created": True,
        "reused": False,
        "admin_url": FOSS_PUBLIC_ADMIN,
    }


def _split_domain(domain: str) -> tuple[str, str]:
    parts = domain.strip().lower().split(".")
    if len(parts) < 2:
        return (parts[0], "com.br")
    return (parts[0], ".".join(parts[1:]))


def create_order(
    *,
    client_id: int | str,
    product_slug: str,
    domain: str,
    period: str = "1M",
    activate: bool = True,
    config: dict[str, Any] | None = None,
    manager_email: str | None = None,
    manager_name: str | None = None,
) -> dict[str, Any]:
    """Cria e activa pedido hosting FOSS (Spec 043 §4.2)."""
    product = find_product_by_slug(product_slug)
    if not product:
        raise RuntimeError(f"produto FOSS não encontrado: {product_slug}")
    product_id = product.get("id")
    sld, tld = _split_domain(domain)
    payload: dict[str, Any] = {
        "client_id": client_id,
        "product_id": product_id,
        "period": period,
        "currency": "BRL",
        "activate": 1 if activate else 0,
        "config": {
            "domain": {
                "action": "owndomain",
                "owndomain_sld": sld,
                "owndomain_tld": tld,
            },
        },
    }
    if config:
        for key, val in config.items():
            if val is not None:
                payload["config"][key] = val
    if manager_email:
        payload["config"]["manager_email"] = manager_email
    if manager_name:
        payload["config"]["manager_name"] = manager_name
    payload["config"]["domain_name"] = domain
    result = _post("order/create", payload)
    order_id = _extract_id(result)
    return {
        "order_id": order_id,
        "client_id": client_id,
        "product_id": product_id,
        "product_slug": product_slug,
        "domain": domain,
        "activated": activate,
        "created": True,
    }


def staff_group_name_for_role(desk_role: str) -> str | None:
    return FOSS_GROUP_BY_ROLE.get(desk_role)


def create_staff(*, email: str, name: str, desk_role: str, password: str | None = None) -> dict[str, Any]:
    """Cria staff FOSS — grupo staff deve existir no Admin (manual v1)."""
    group_name = staff_group_name_for_role(desk_role)
    if not group_name:
        return {"skipped": True, "reason": f"role {desk_role} sem grupo FOSS"}
    pwd = password or secrets.token_urlsafe(14)
    payload: dict[str, Any] = {
        "email": email.strip().lower(),
        "name": name,
        "password": pwd,
        "status": "active",
        "admin_group_id": group_name,
    }
    try:
        result = _post("staff/create", payload)
    except RuntimeError as exc:
        if "admin_group" in str(exc).lower() or "group" in str(exc).lower():
            return {"skipped": True, "reason": str(exc), "group": group_name}
        raise
    return {
        "foss_staff_id": result.get("id") or result.get("result"),
        "email": email,
        "group": group_name,
        "admin_url": FOSS_PUBLIC_ADMIN,
        "created": True,
    }
