import uuid
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
from app.core.database import SessionLocal
from app.services.tenant_runtime import resolve_tenant, apply_postgres_tenant_context, ensure_namespace

PUBLIC_PREFIXES=('/health','/docs','/openapi.json','/static','/manifest.webmanifest','/service-worker.js')
class TenantRuntimeMiddleware(BaseHTTPMiddleware):
    async def dispatch(self,request,call_next):
        request.state.request_id=request.headers.get('X-Request-ID') or str(uuid.uuid4())
        request.state.tenant=None; request.state.tenant_namespace=None
        tenant_id=request.headers.get('X-Tenant-ID','').strip()
        host=request.headers.get('host','')
        if tenant_id or (host and not request.url.path.startswith(PUBLIC_PREFIXES)):
            db=SessionLocal()
            try:
                tenant=resolve_tenant(db,tenant_id,host) if tenant_id else None
                if tenant_id and not tenant:
                    return JSONResponse({'detail':'Tenant ativo não encontrado','request_id':request.state.request_id},status_code=404)
                if tenant:
                    apply_postgres_tenant_context(db,tenant.id)
                    request.state.tenant=tenant
                    request.state.tenant_namespace=ensure_namespace(db,tenant)
            except ValueError:
                pass
            finally: db.close()
        response=await call_next(request)
        response.headers['X-Request-ID']=request.state.request_id
        if request.state.tenant: response.headers['X-Tenant-ID']=request.state.tenant.id
        return response
