import { Request, Response, NextFunction } from "express";
import { checkAccess } from "../services/authz";

type CrudAction = "create" | "read" | "update" | "delete" | "admin" | "view";

function isNonEmptyString(v: unknown): v is string {
  return typeof v === "string" && v.trim().length > 0;
}

export function requireAccess(
  getConfig: (req: Request) => {
    userId: string;
    resourceName: string;
    action: CrudAction;
  }
) {
  return async (req: Request, res: Response, next: NextFunction) => {
    try {
      const cfg = getConfig(req);

      const userId = cfg?.userId;
      const resourceName = cfg?.resourceName;
      const action = cfg?.action;

      // ✅ Validate early (prevents calling OPA with undefined/null)
      if (!isNonEmptyString(userId) || !isNonEmptyString(resourceName) || !isNonEmptyString(action)) {
        return res.status(400).json({
          message: "Missing or invalid authorization inputs",
          details: {
            userId: userId ?? null,
            resourceName: resourceName ?? null,
            action: action ?? null,
          },
        });
      }

      console.log("AUTHZ INPUT:", { userId, resourceName, action });

      // checkAccess MUST build:
      // { input: { user: {id:userId}, resource:{name:resourceName}, action } }
      const allowed = await checkAccess({ userId, resourceName, action });

      console.log("AUTHZ RESULT:", allowed);

      if (!allowed) {
        return res.status(403).json({ message: "Forbidden: access denied" });
      }

      return next();
    } catch (e: any) {
      return res.status(502).json({
        message: "Authorization service error",
        error: e?.message ?? "Unknown error",
      });
    }
  };
}
