from __future__ import annotations
from contextlib import asynccontextmanager
from typing import AsyncIterator, Mapping

from fastapi import Request, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession

from .config import TenantsConfig
from .registry import TenantsRegistry
from .db import tenant_session, dispose_all_engines


def resolve_tenant_name(config: TenantsConfig, registry: TenantsRegistry, headers: Mapping[str, str]) -> str:
    tenant = (headers.get(config.tenant_header) or config.default_tenant).strip().lower()
    if not tenant:
        tenant = config.default_tenant

    if config.allowed_tenants_csv:
        allowed = {x.strip().lower() for x in config.allowed_tenants_csv.split(",") if x.strip()}
        if config.strict_whitelist and tenant not in allowed:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Tenant non consentito")

    if not registry.exists(tenant):
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Tenant '{tenant}' non trovato")

    return tenant


def make_tenant_session_dep(config: TenantsConfig, registry: TenantsRegistry):
    @asynccontextmanager
    async def _dep(request: Request) -> AsyncIterator[AsyncSession]:
        tenant = resolve_tenant_name(config, registry, request.headers)
        async with tenant_session(config, tenant, registry) as session:
            yield session
    return _dep


async def shutdown_tenants():
    await dispose_all_engines()
