import { Request, Response } from "express";
import Stacker from "../middlewares/stacker.js";
import {
   ClientAuthMiddleware,
   GetClientAuthMiddleware,
} from "../middlewares/client.js";
import Permission from "../../models/permissions.js";
import User from "../../models/user.js";

import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
import Grant from "../../models/grants.js";
import { ObjectId } from "mongodb";

export const GetPermissions = Stacker(
   GetClientAuthMiddleware(true),
   async (req: Request, res: Response) => {
      const { user, permission } = req.query as { [key: string]: string };

      let permissions: { id: string; name: string; description: string }[];
      let users: string[];

      if (user) {
         const grant = await Grant.findOne({
            client: req.client._id,
            user: new ObjectId(user),
         });

         permissions = await Promise.all(
            grant.permissions.map((perm) => Permission.findById(perm))
         ).then((res) =>
            res
               .filter((e) => e.grant_type === "client")
               .map((e) => {
                  return {
                     id: e._id.toHexString(),
                     name: e.name,
                     description: e.description,
                  };
               })
         );
      }

      if (permission) {
         const grants = await Grant.find({
            client: req.client._id,
            permissions: new ObjectId(permission),
         });

         users = grants.map((grant) => grant.user.toHexString());
      }

      res.json({ permissions, users });
   }
);

export const PostPermissions = Stacker(
   GetClientAuthMiddleware(true),
   async (req: Request, res: Response) => {
      const { permission, uid } = req.body;

      const user = await User.findOne({ uid });
      if (!user) {
         throw new RequestError("User not found!", HttpStatusCode.BAD_REQUEST);
      }

      const permissionDoc = await Permission.findById(permission);
      if (!permissionDoc || !permissionDoc.client.equals(req.client._id)) {
         throw new RequestError(
            "Permission not found!",
            HttpStatusCode.BAD_REQUEST
         );
      }

      let grant = await Grant.findOne({
         client: req.client._id,
         user: req.user._id,
      });

      if (!grant) {
         grant = Grant.new({
            client: req.client._id,
            user: req.user._id,
            permissions: [],
         });
      }

      //TODO: Fix clients getting user data without consent, when a grant is created and no additional permissions are requested, since for now, it is only checked for grant existance to make client access user data

      if (grant.permissions.indexOf(permission) < 0)
         grant.permissions.push(permission);

      await Grant.save(grant);

      res.json({
         success: true,
      });
   }
);
