"""
Cashier Access Control Middleware - enforces role-based route restrictions
"""
from fastapi import Request, status
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
from sqlalchemy.orm import Session
from app.core.database import SessionLocal
from app.core.security import get_current_user
from app.models.user import User
from jose import jwt, JWTError
from app.core.security import SECRET_KEY, ALGORITHM

# Routes that cashier/pos_user roles are allowed to access
CASHIER_ALLOWED_PREFIXES = [
    "/api/v1/pos/",
    "/api/v1/sales/",
    "/api/v1/inventory/products/",
    "/api/v1/customers/",
    "/api/v1/banking/bank-accounts",
    "/api/v1/banking/transactions",
    "/api/v1/receipts/",
    "/api/v1/auth/",
    "/api/v1/settings/",
    "/api/v1/app-setting/",
    "/api/v1/app-settings/",
    "/api/v1/notifications/",
]

# Routes explicitly blocked for cashier/pos_user
CASHIER_FORBIDDEN_PREFIXES = [
    "/api/v1/accounting/",
    "/api/v1/accounting-codes/",
    "/api/v1/accounting_codes/",
    "/api/v1/general-ledger/",
    "/api/v1/journal-entries/",
    "/api/v1/vat/",
    "/api/v1/users/",
    "/api/v1/roles/",
    "/api/v1/branches/",
    "/api/v1/purchases/",
    "/api/v1/procurement/",
    "/api/v1/asset-management/",
    "/api/v1/backup/",
    "/api/v1/invoice-designer/",
    "/api/v1/workflows/",
    "/api/v1/manufacturing/",
    "/api/v1/budgeting/",
    "/api/v1/reports/",
]


class CashierAccessControlMiddleware(BaseHTTPMiddleware):
    """
    Middleware that enforces route restrictions for cashier/pos_user roles.
    Allows them to access only POS-related endpoints.
    """

    async def dispatch(self, request: Request, call_next):
        path = request.url.path

        # Skip non-API routes
        if not path.startswith("/api/v1/"):
            return await call_next(request)

        # Get user role from JWT token if present
        role = None
        auth_header = request.headers.get("Authorization", "")
        if auth_header.startswith("Bearer "):
            token = auth_header[7:]
            try:
                payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
                role = payload.get("role", "").lower()
            except JWTError:
                pass

        # Only restrict cashier/pos_user roles
        if role not in ('cashier', 'pos_user'):
            return await call_next(request)

        # Check if route is explicitly forbidden
        for forbidden in CASHIER_FORBIDDEN_PREFIXES:
            if path.startswith(forbidden):
                return JSONResponse(
                    status_code=status.HTTP_403_FORBIDDEN,
                    content={
                        "detail": "Cashier users cannot access this feature. Only POS and sales functions are available."
                    }
                )

        # Check if route is allowed (if not in allowed list, deny)
        is_allowed = False
        for allowed in CASHIER_ALLOWED_PREFIXES:
            if path.startswith(allowed):
                is_allowed = True
                break

        if not is_allowed:
            return JSONResponse(
                status_code=status.HTTP_403_FORBIDDEN,
                content={
                    "detail": "Cashier users are restricted to POS operations only. This endpoint is not available for your role."
                }
            )

        return await call_next(request)
