import { type Request, type Response } from 'express';
import ipaddr from 'ipaddr.js';

import { getSession } from '../account-db';
import { config } from '../load-config';

export const TOKEN_EXPIRATION_NEVER = -1;
const MS_PER_SECOND = 1000;

export function validateSession(req: Request, res: Response) {
  let { token } = req.body || {};

  if (!token) {
    token = req.headers['x-actual-token'];
  }

  const session = getSession(token);

  if (!session) {
    res.status(401);
    res.send({
      status: 'error',
      reason: 'unauthorized',
      details: 'token-not-found',
    });
    return null;
  }

  if (
    session.expires_at !== TOKEN_EXPIRATION_NEVER &&
    session.expires_at * MS_PER_SECOND <= Date.now()
  ) {
    res.status(401);
    res.send({
      status: 'error',
      reason: 'token-expired',
    });
    return null;
  }

  return session;
}

export function validateAuthHeader(req: Request) {
  // fallback to trustedProxies when trustedAuthProxies not set
  const trustedAuthProxies: string[] =
    config.get('trustedAuthProxies') ?? config.get('trustedProxies');
  // ensure the first hop from our server is trusted
  const peer = req.socket.remoteAddress;
  if (peer === undefined) {
    console.error(`Header Auth Login attempted but there was no defined peer.`);
    return false;
  }
  const peerIp = ipaddr.process(peer);
  const rangeList = {
    allowed_ips: trustedAuthProxies.map(q => ipaddr.parseCIDR(q)),
  };

  const matched = ipaddr.subnetMatch(peerIp, rangeList, 'fail');

  if (matched === 'allowed_ips') {
    console.info(`Header Auth Login permitted from ${peer}`);
    return true;
  } else {
    console.warn(`Header Auth Login attempted from ${peer}`);
    return false;
  }
}
