import { Router, Request } from "express";
import RequestError, { HttpStatusCode } from "../../helper/request_error.js";
import promiseMiddleware from "../../helper/promiseMiddleware.js";
import Client from "../../models/client.js";
import verify, { Types } from "../middlewares/verify.js";
import { randomBytes } from "crypto";

const ClientRouter: Router = Router();
ClientRouter.route("/")
   /**
    * @api {get} /admin/client
    * @apiName AdminGetClients
    *
    * @apiGroup admin_client
    * @apiPermission admin
    *
    * @apiSuccess {Object[]} clients
    * @apiSuccess {String} clients._id The internally used id
    * @apiSuccess {String} clients.maintainer
    * @apiSuccess {Boolean} clients.internal
    * @apiSuccess {String} clients.name
    * @apiSuccess {String} clients.redirect_url
    * @apiSuccess {String} clients.website
    * @apiSuccess {String} clients.logo
    * @apiSuccess {String} clients.client_id Client ID used outside of DB
    * @apiSuccess {String} clients.client_secret
    */
   .get(
      promiseMiddleware(async (req, res) => {
         let clients = await Client.find({});
         //ToDo check if user is required!
         res.json(clients);
      })
   )
   /**
    * @api {get} /admin/client
    * @apiName AdminAddClients
    *
    * @apiGroup admin_client
    * @apiPermission admin
    *
    * @apiParam {Boolean} internal Is it an internal app
    * @apiParam {String} name
    * @apiParam {String} redirect_url
    * @apiParam {String} website
    * @apiParam {String} logo
    *
    * @apiSuccess {Object[]} clients
    * @apiSuccess {String} clients._id The internally used id
    * @apiSuccess {String} clients.maintainer
    * @apiSuccess {Boolean} clients.internal
    * @apiSuccess {String} clients.name
    * @apiSuccess {String} clients.redirect_url
    * @apiSuccess {String} clients.website
    * @apiSuccess {String} clients.logo
    * @apiSuccess {String} clients.client_id Client ID used outside of DB
    * @apiSuccess {String} clients.client_secret
    */
   .post(
      verify(
         {
            internal: {
               type: Types.BOOLEAN,
               optional: true,
            },
            name: {
               type: Types.STRING,
            },
            redirect_url: {
               type: Types.STRING,
            },
            website: {
               type: Types.STRING,
            },
            logo: {
               type: Types.STRING,
               optional: true,
            },
            featured: {
               type: Types.BOOLEAN,
               optional: true,
            },
            description: {
               type: Types.STRING,
               optional: true,
            },
         },
         true
      ),
      promiseMiddleware(async (req, res) => {
         req.body.client_secret = randomBytes(32).toString("hex");
         let client = Client.new(req.body);
         client.maintainer = req.user._id;
         await Client.save(client);
         res.json(client);
      })
   );

ClientRouter.route("/:id")
   /**
    * @api {delete} /admin/client/:id
    * @apiParam {String} id Client _id
    * @apiName AdminDeleteClient
    *
    * @apiGroup admin_client
    * @apiPermission admin
    *
    * @apiSuccess {Boolean} success
    */
   .delete(
      promiseMiddleware(async (req, res) => {
         let { id } = req.params;
         await Client.delete(id);
         res.json({ success: true });
      })
   )
   /**
    * @api {put} /admin/client/:id
    * @apiParam {String} id Client _id
    * @apiName AdminUpdateClient
    *
    * @apiGroup admin_client
    * @apiPermission admin
    *
    * @apiParam {Boolean} internal Is it an internal app
    * @apiParam {String} name
    * @apiParam {String} redirect_url
    * @apiParam {String} website
    * @apiParam {String} logo
    *
    * @apiSuccess {String} _id The internally used id
    * @apiSuccess {String} maintainer UserID of client maintainer
    * @apiSuccess {Boolean} internal Defines if it is a internal client
    * @apiSuccess {String} name The name of the Client
    * @apiSuccess {String} redirect_url Redirect URL after login
    * @apiSuccess {String} website Website of Client
    * @apiSuccess {String} logo The Logo of the Client (optional)
    * @apiSuccess {String} client_id Client ID used outside of DB
    * @apiSuccess {String} client_secret The client secret, that can be used to obtain token
    */
   .put(
      verify(
         {
            internal: {
               type: Types.BOOLEAN,
               optional: true,
            },
            name: {
               type: Types.STRING,
               optional: true,
            },
            redirect_url: {
               type: Types.STRING,
               optional: true,
            },
            website: {
               type: Types.STRING,
               optional: true,
            },
            logo: {
               type: Types.STRING,
               optional: true,
            },
            featured: {
               type: Types.BOOLEAN,
               optional: true,
            },
            description: {
               type: Types.STRING,
               optional: true,
            },
         },
         true
      ),
      promiseMiddleware(async (req, res) => {
         let { id } = req.query as { [key: string]: string };
         let client = await Client.findById(id);
         if (!client)
            throw new RequestError(
               req.__("Client not found"),
               HttpStatusCode.BAD_REQUEST
            );
         for (let key in req.body) {
            client[key] = req.body[key];
         }
         await Client.save(client);
         res.json(client);
      })
   );

export default ClientRouter;
