import { Request, Response, Router } from "express";
import Stacker from "../middlewares/stacker.js";
import {
   GetClientAuthMiddleware,
   GetClientApiAuthMiddleware,
} from "../middlewares/client.js";
import { GetUserMiddleware } from "../middlewares/user.js";
import { createJWT } from "../../keys.js";
import Client from "../../models/client.js";
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
import config from "../../config.js";
import Mail from "../../models/mail.js";

const ClientRouter = Router();

/**
 * @api {get} /client/user
 *
 * @apiDescription Can be used for simple authentication of user. It will redirect the user to the redirect URI with a very short lived jwt.
 *
 * @apiParam {String} redirect_uri URL to redirect to on success
 * @apiParam {String} state A optional state, that will be included in the JWT and redirect_uri as parameter
 *
 * @apiName ClientUser
 * @apiGroup client
 *
 * @apiPermission user_client Requires ClientID and Authenticated User
 */
ClientRouter.get(
   "/user",
   Stacker(
      GetClientAuthMiddleware(false),
      GetUserMiddleware(false, false),
      async (req: Request, res: Response) => {
         let { redirect_uri, state } = req.query;

         if (redirect_uri !== req.client.redirect_url)
            throw new RequestError(
               "Invalid redirect URI",
               HttpStatusCode.BAD_REQUEST
            );

         let jwt = await createJWT(
            {
               client: req.client.client_id,
               uid: req.user.uid,
               username: req.user.username,
               state: state,
            },
            {
               expiresIn: 30,
               issuer: config.core.url,
               algorithm: "RS256",
               subject: req.user.uid,
               audience: req.client.client_id,
            }
         ); //after 30 seconds this token is invalid
         res.redirect(
            redirect_uri + "?jwt=" + jwt + (state ? `&state=${state}` : "")
         );
      }
   )
);

ClientRouter.get(
   "/account",
   Stacker(GetClientApiAuthMiddleware(), async (req: Request, res) => {
      let mails = await Promise.all(
         req.user.mails.map((id) => Mail.findById(id))
      );

      let mail = mails.find((e) => e.primary) || mails[0];

      res.json({
         user: {
            username: req.user.username,
            name: req.user.name,
            email: mail,
         },
      });
   })
);

/**
 * @api {get} /client/featured
 *
 * @apiDescription Get a list of clients, that want to be featured on the home page
 *
 * @apiName GetFeaturedClients
 * @apiGroup client
 */
ClientRouter.get(
   "/featured",
   Stacker(async (req: Request, res) => {
      let clients = await Client.find({
         featured: true,
      });

      res.json({
         clients: clients.map(({ name, logo, website, description }) => ({
            name,
            logo,
            website,
            description,
         })),
      });
   })
);

export default ClientRouter;
