import { Route, Server } from '../../../class';
import { RedirectRaw } from '../../../models';

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

  public bind() {
    this.router.get('/', (_req, res) => res.redirect('https://www.libraryofcode.org/'));

    this.router.get('/dash', async (req, res) => {
      try {
        const lookup = await this.server.client.db.CustomerPortal.findOne({ key: req.query.q?.toString() });
        if (!lookup) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.messages.NOT_FOUND });
        if (new Date(lookup.expiresOn) < new Date()) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED });

        const customer = await this.server.client.db.Customer.findOne({ userID: lookup.userID });
        if (!customer) {
          const newCus = await this.server.client.stripe.customers.create({
            email: lookup.emailAddress,
            metadata: {
              userID: lookup.userID,
              username: lookup.username,
            },
          });
          await (new this.server.client.db.Customer({
            cusID: newCus.id,
            userID: lookup.userID,
          })).save();
          const billingURL = await this.server.client.stripe.billingPortal.sessions.create({
            customer: newCus.id,
            return_url: 'https://www.libraryofcode.org',
          });
          res.redirect(302, billingURL.url);
          return await lookup.updateOne({ $set: { used: true } });
        }
        const billingURL = await this.server.client.stripe.billingPortal.sessions.create({
          customer: customer.cusID,
          return_url: 'https://www.libraryofcode.org',
        });
        res.redirect(302, billingURL.url);
        return await lookup.updateOne({ $set: { used: true } });
      } catch (err) {
        return this.handleError(err, res);
      }
    });

    this.router.get('/:key', async (req, res) => {
      try {
        const link: RedirectRaw = await this.server.client.db.Redirect.findOne({ key: req.params.key }).lean().exec();
        if (!link) return res.status(404).json({ code: this.constants.codes.NOT_FOUND, message: this.constants.messages.NOT_FOUND });
        res.redirect(link.to);
        return await this.server.client.db.Redirect.updateOne({ key: req.params.key }, { $inc: { visitedCount: 1 } });
      } catch (err) {
        this.server.client.util.handleError(err);
        return res.status(500).json({ code: this.constants.codes.SERVER_ERROR, message: this.constants.messages.SERVER_ERROR });
      }
    });
  }
}
