"""Explicit method/route policy. Unlisted registered endpoints fail closed."""
import json
from pathlib import Path
from fastapi import HTTPException
from starlette.routing import Match


def policies():
    doc=json.loads((Path(__file__).resolve().parents[1]/'docs/access-policy.json').read_text())
    if doc['default']!='deny':raise ValueError('Access policy must deny by default.')
    result={}
    for item in doc['routes']:
        key=(item['method'],item['path']);access=item['access']
        if key in result or access not in ('public','portal','member','owner','staff'):raise ValueError('Invalid access policy inventory.')
        result[key]=access
    return result


def enforce(app,request,auth,policy):
    route=next((r for r in app.routes if r.matches(request.scope)[0]==Match.FULL),None)
    if route is None:
        if any(r.matches(request.scope)[0]==Match.PARTIAL for r in app.routes):raise HTTPException(405,'Method not allowed.')
        raise HTTPException(404,'Route not found.')
    access=policy.get((request.method,route.path))
    if access is None:raise HTTPException(403,'This endpoint has no approved local access policy.')
    if access=='public':return
    s=auth.session(request,'portal' if access=='portal' else 'staff',request.method not in ('GET','HEAD','OPTIONS'))
    if access in ('owner','staff') and s.get('role')!=access:raise HTTPException(403,'Your role does not permit that action.')
