"""HTTP RequestContext — session 解析与向后兼容 owner 默认。"""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Any

from starlette.requests import Request

from niannian.tenant.capabilities import capabilities_for_login, capabilities_for_role
from niannian.tenant.intranet import is_desktop_agent_request
from niannian.tenant.registry import TenantUserRegistry
from niannian.tenant.sessions import TenantSessionStore
from niannian.tenant.tenant_auth_settings import TenantAuthSettings

SESSION_HEADER = "x-niannian-session"
DEFAULT_OWNER_USER_ID = "pinn"


@dataclass(frozen=True)
class RequestContext:
    user_id: str
    role: str
    capabilities: list[str]
    session_token: str | None = None

    def to_dict(self) -> dict[str, Any]:
        payload: dict[str, Any] = {
            "username": self.user_id,
            "role": self.role,
            "capabilities": list(self.capabilities),
        }
        if self.session_token:
            payload["token"] = self.session_token
        return payload


def _session_header(request: Request) -> str | None:
    raw = request.headers.get(SESSION_HEADER) or request.headers.get("X-NianNian-Session")
    if raw is None:
        return None
    value = str(raw).strip()
    return value or None


def resolve_request_context(
    request: Request,
    config: dict[str, Any],
    *,
    home: Path | None = None,
    sessions: TenantSessionStore | None = None,
) -> RequestContext:
    token = _session_header(request)
    if not token:
        return RequestContext(
            user_id=DEFAULT_OWNER_USER_ID,
            role="owner",
            capabilities=capabilities_for_login("owner", intranet_console=True),
        )

    store = sessions
    data_home = home
    if store is None:
        from niannian.config import resolve_data_home

        data_home = home or resolve_data_home(config.get("data_home"))
        store = TenantSessionStore(data_home)
    elif data_home is None:
        data_home = store.path.parent.parent

    session = store.validate(token)
    if session is None:
        return RequestContext(
            user_id=DEFAULT_OWNER_USER_ID,
            role="owner",
            capabilities=capabilities_for_login("owner", intranet_console=True),
        )

    registry = TenantUserRegistry(data_home)
    row = registry.get_user(session.username)
    role = "tenant"
    if isinstance(row, dict):
        role = str(row.get("role", "tenant")).lower()
        if role not in ("owner", "tenant"):
            role = "tenant"

    from_agent = is_desktop_agent_request(
        agent_header=request.headers.get("x-niannian-agent") or request.headers.get("X-NianNian-Agent"),
    )
    # Agent header on API calls; default client surface for owner unless intranet_console session
    caps = capabilities_for_login(
        role,
        desktop_agent=from_agent or not session.intranet_console,
        intranet_console=session.intranet_console,
    )

    return RequestContext(
        user_id=session.username,
        role=role,
        capabilities=caps,
        session_token=session.token,
    )


def tenant_login_enabled(config: dict[str, Any], *, home: Path | None = None) -> bool:
    if home is not None:
        return TenantAuthSettings(home).login_enabled(config)
    from niannian.config import resolve_data_home

    return TenantAuthSettings(resolve_data_home(config.get("data_home"))).login_enabled(config)
