import bodyParser from 'body-parser';
import { declareHandler } from '../server-utils/routesHandler.js';

const EXPECTED_PROJECT_IDS = ['4505010940346368', '4504950924312576'];

const SENTRY_DSN_REGEX = /^[0-9a-zA-Z]+\.ingest\.sentry\.io$/;

const sentryTunnel = declareHandler({
  func: async (req, res) => {
    const envelope = req.body as Buffer;
    if (!(envelope instanceof Buffer)) {
      return res.status(400).send('Bad Request');
    }
    const newlineIndex = envelope.indexOf('\n');
    if (newlineIndex === -1) {
      return res.status(400).send('Bad Request');
    }
    const firstPiece = envelope.subarray(0, newlineIndex);
    const restPiece = envelope.subarray(newlineIndex);
    const header = JSON.parse(firstPiece.toString('utf8'));

    const { host, pathname, username } = new URL(header.dsn);

    const projectId = pathname.slice(1);

    if (!EXPECTED_PROJECT_IDS.includes(projectId) || !SENTRY_DSN_REGEX.test(host)) {
      return res.status(403).send('Forbidden');
    }

    const url = `https://${host}/api/${projectId}/envelope/?sentry_key=${username}`;

    const newHeader = {
      ...header,
      forwarded_for:
        typeof req.headers['x-forwarded-for'] === 'string' ? req.headers['x-forwarded-for'] : req.socket.remoteAddress,
    };

    const subreq = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-sentry-envelope',
      },
      body: Buffer.concat([Buffer.from(JSON.stringify(newHeader), 'utf8'), restPiece]),
    });

    const subreqContentType = subreq.headers.get('Content-Type');
    if (subreqContentType !== null) {
      res.setHeader('Content-Type', subreqContentType);
    }

    return res.status(subreq.status).send(Buffer.from(await subreq.arrayBuffer()));
  },
  middleware: bodyParser.raw({ type: '*/*', limit: '10mb', inflate: true }),
});

export default sentryTunnel;
