"""
Blocks API access when the tenant license is expired (after grace period).
"""
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import JSONResponse

from app.core.config import settings
from app.core.database import SessionLocal
from app.services.licensing_service import LicensingService

_OPEN_PREFIXES = (
    "/static",
    "/docs",
    "/redoc",
    "/openapi.json",
    "/health",
    "/metrics",
    "/setup",
    "/home",
    "/install",
)

_OPEN_EXACT = {
    "/",
    "/api/v1/auth/login-json",
    "/api/v1/auth/login-direct",
    "/api/v1/auth/login-test",
    "/api/v1/auth/login-branches",
    "/api/v1/auth/login-branches/health",
    "/api/v1/companies/register",
    "/api/v1/companies/register-full",
    "/api/v1/companies/check-setup",
    "/api/v1/licensing/validate",
    "/api/v1/licensing/nodes/register",
    "/api/v1/licensing/nodes/heartbeat",
    "/api/v1/sync/ingest",
    "/api/v1/licensing/verify-setup",
    "/api/v1/licensing/claim-setup",
}


class LicenseMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        if not settings.license_enforcement:
            return await call_next(request)

        path = request.url.path
        if path.startswith(_OPEN_PREFIXES) or path in _OPEN_EXACT:
            return await call_next(request)
        if path.startswith("/api/v1/companies/lookup/"):
            return await call_next(request)
        if path.startswith("/api/v1/licensing/keys") or path.startswith("/api/v1/licensing/admin"):
            return await call_next(request)
        if path.startswith("/api/v1/platform/"):
            return await call_next(request)
        if path.startswith("/api/v1/installer/"):
            return await call_next(request)

        company_id = getattr(request.state, "company_id", None)
        if not company_id:
            return await call_next(request)

        db = SessionLocal()
        try:
            status = LicensingService(db).company_license_status(company_id)
            if not status.get("licensed"):
                return JSONResponse(
                    status_code=402,
                    content={
                        "success": False,
                        "error": "license_expired",
                        "message": status.get("message", "License expired or missing"),
                        "status": status.get("status"),
                    },
                )
        finally:
            db.close()

        return await call_next(request)
