import axios, { AxiosResponse } from 'axios';
import { Route, Server } from '../../../class';

import { X509Certificate } from '../../../commands/x509';
import { PGPKey, PublicKeyAlgorithm } from '../../../commands/pgp';

export default class Keys extends Route {
  constructor(server: Server) {
    super(server);
    this.conf = {
      path: '/keys',
    };
  }

  public bind() {
    this.router.all('*', (_req, res, next) => {
      res.setHeader('Access-Control-Allow-Origin', '*');
      res.setHeader('Access-Control-Allow-Methods', '*');
      res.setHeader('Access-Control-Allow-Headers', '*');
      next();
    });

    this.router.get('/p/:type/x509/:userID', async (req, res) => {
      const memberDoc = await this.server.client.db.mongo.Member.findOne({ userID: req.params.userID }).lean().exec();
      const member = this.mainGuild.members.get(req.params.userID);
      if (!member || !memberDoc || !memberDoc?.x509) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.messages.NOT_FOUND });
      if (req.params.type === 'download') res.contentType('application/x-x509-user-cert');
      return res.status(200).send(memberDoc.x509);
    });

    this.router.get('/p/:type/pgp/:userID', async (req, res) => {
      const memberDoc = await this.server.client.db.mongo.Member.findOne({ userID: req.params.userID }).lean().exec();
      const member = this.mainGuild.members.get(req.params.userID);
      if (!member || !memberDoc || !memberDoc?.pgp) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.messages.NOT_FOUND });
      if (req.params.type === 'download') res.contentType('application/pgp-keys');
      return res.status(200).send(memberDoc.pgp);
    });

    // this.router.get('/confirm/pgp/:jwt', async (req, res) => {
    //  const data: { pgp: string, userID: string } = jwt.verify(req.params.jwt, this.server.client.config.internalKey);
    // })

    this.router.get('/~/x509/:userID', async (req, res) => {
      const memberDoc = await this.server.client.db.mongo.Member.findOne({ userID: req.params.userID }).lean().exec();
      const member = this.mainGuild.members.get(req.params.userID);
      if (!member || !memberDoc || !memberDoc?.x509) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.messages.NOT_FOUND });

      const x509: AxiosResponse<X509Certificate> = await axios.post('https://certapi.libraryofcode.org/parse', memberDoc.x509);

      res.status(200).send(`
      <head>
        <title>x509 Certificate ${x509.data.serialNumber}</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta property="og:title" content="x509 Certificate ${x509.data.serialNumber}">
        <meta property="og:type" content="website">
        <meta property="og:description" content="x509 Certificate Information for ${x509.data.subject.commonName}">
      </head>
      <body>
        <p><strong>Discord Username + Discriminator</strong> ${member.username}#${member.discriminator} (${member.id})</p>
        
        <p><strong>Common Name:</strong> ${x509.data.subject.commonName}</p>
        <p><strong>Email Address:</strong> ${x509.data.emailAddresses[0]}</p>
        <p><strong>Expires on:</strong> ${new Date(x509.data.notAfter).toLocaleString('en-us')}</p>

        <p><strong>Public Key Algorithm</strong> ${x509.data.publicKeyAlgorithm}</p>
        <p><strong>Key Bit Length</strong> ${x509.data.bitLength}</p>
        <p><strong>Signature Algorithm</strong> ${x509.data.signatureAlgorithm}</p>
        <p><strong>Serial Number</strong> ${x509.data.serialNumber}</p>
        <p><strong>Fingerprint</strong> ${x509.data.fingerprint}</p>

        <p><strong>Issuer:</strong> ${x509.data.issuer.organization} (${x509.data.issuer.commonName})</p>
        <br><br><br>
        ${memberDoc.x509.replace(/(?:\r\n|\r|\n)/g, '<br>')}
      `);
    });

    this.router.get('/~/pgp/:userID', async (req, res) => {
      const memberDoc = await this.server.client.db.mongo.Member.findOne({ userID: req.params.userID }).lean().exec();
      const member = this.mainGuild.members.get(req.params.userID);
      if (!member || !memberDoc || !memberDoc?.pgp) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.messages.NOT_FOUND });

      const pgp: AxiosResponse<PGPKey> = await axios.post('https://certapi.libraryofcode.org/pgp', memberDoc.pgp);

      let algo: string;
      switch (pgp.data.publicKeyAlgorithm) {
        case PublicKeyAlgorithm.DSA:
          algo = 'DSA';
          break;
        case PublicKeyAlgorithm.ECDH:
          algo = 'ECDH';
          break;
        case PublicKeyAlgorithm.ECDSA:
          algo = 'ECDSA';
          break;
        case PublicKeyAlgorithm.ElGamal:
          algo = 'ElGamal';
          break;
        case PublicKeyAlgorithm.RSA:
          algo = 'RSA';
          break;
        default:
          algo = 'N/A';
          break;
      }

      res.status(200).send(`
      <head>
        <title>PGP Key ${pgp.data.keyID}</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta property="og:title" content="PGP Key ${pgp.data.keyID}">
        <meta property="og:type" content="website">
        <meta property="og:description" content="PGP Key Information for ${pgp.data.fullName}">
      </head>
      <body>
        <p><strong>Discord Username + Discriminator</strong> ${member.username}#${member.discriminator} (${member.id})</p>

        <p><strong>Name:</strong> ${pgp.data.name}</p>
        <p><strong>Email Address:</strong> ${pgp.data.email}</p>
        <p><strong>Comment:</strong> ${pgp.data.comment}</p>

        <p><strong>Public Key Algorithm:</strong> ${algo}</p>
        <p><strong>Key Bit Length:</strong> ${pgp.data.bitLength}</p>
        <p><strong>Key ID:</strong> ${pgp.data.keyID}</p>
        <p><strong>Fingerprint:</strong> ${pgp.data.fingerprint}</p>
        <br><br><br>
        ${memberDoc.pgp.replace(/(?:\r\n|\r|\n)/g, '<br>')}
      `);
    });
  }
}
