import http from 'node:http';

import { configFromEnv } from './config.js';
import { AppserviceDaemon } from './server.js';

const cfg = configFromEnv();
const daemon = new AppserviceDaemon(cfg);

const MAX_BODY_BYTES = 1024 * 1024;

const server = http.createServer((req, res) => {
  const chunks: Buffer[] = [];
  let received = 0;
  let rejected = false;
  req.on('data', (chunk: Buffer) => {
    received += chunk.length;
    if (received > MAX_BODY_BYTES) {
      rejected = true;
      res.writeHead(413, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ errcode: 'M_TOO_LARGE', error: 'request body too large' }));
      req.destroy();
      return;
    }
    chunks.push(chunk);
  });
  req.on('end', () => {
    if (rejected) return;
    void (async () => {
      const url = new URL(req.url ?? '/', 'http://localhost');
      let body: unknown;
      try {
        const raw = Buffer.concat(chunks).toString();
        body = raw ? JSON.parse(raw) : undefined;
      } catch {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ errcode: 'M_NOT_JSON', error: 'invalid json' }));
        return;
      }
      const result = await daemon.handle({
        method: req.method ?? 'GET',
        path: url.pathname,
        searchParams: url.searchParams,
        authorizationHeader: req.headers.authorization,
        body,
      });
      res.writeHead(result.status, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify(result.body));
    })().catch((error: unknown) => {
      console.error('request failed:', error);
      if (res.headersSent) {
        res.destroy();
        return;
      }
      res.writeHead(500, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ error: 'internal error' }));
    });
  });
});

server.listen(cfg.port, () => {
  console.log(
    `mosaic-as listening on :${cfg.port} (homeserver ${cfg.homeserverUrl}, domain ${cfg.domain})`,
  );
  if (cfg.bridgeTokens.length === 0) {
    console.warn('WARNING: MOSAIC_AS_BRIDGE_TOKENS is empty — bridge API will deny all requests');
  }
});
