import express from 'express';
import type { Application } from 'express';
import session from 'express-session';
import helmet from 'helmet';
import type { DatabaseSync } from 'node:sqlite';
import type { EventEmitter } from 'node:events';
import { createApiRouter } from './routes/index.ts';
import type { UrlGuard } from './services/ingest.ts';
import type { BusEvents } from './events.ts';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

export interface AppConfig {
  SESSION_SECRET: string;
  NODE_ENV?: string;
  PORT?: number;
}

export interface CreateAppOptions {
  config?: AppConfig;
  db?: DatabaseSync;
  guard?: UrlGuard;
  bus?: EventEmitter<BusEvents>;
}

export function createApp(options: CreateAppOptions = {}): Application {
  const { config, db, guard, bus } = options;
  const app = express();
  app.use(helmet());
  app.use(express.json());
  if (config) {
    app.use(
      session({
        secret: config.SESSION_SECRET,
        resave: false,
        saveUninitialized: false,
        cookie: {
          httpOnly: true,
          // 'auto' marks the cookie Secure only when the request itself is HTTPS.
          // Forcing Secure in production breaks plain-HTTP deployments (e.g. docker compose).
          secure: 'auto',
          sameSite: 'lax',
        },
      }),
    );
  }
  app.get('/healthz', (_req, res) => res.json({ status: 'ok' }));
  if (db) {
    app.use('/api', createApiRouter(db, guard, bus));
  }

  const clientDist = path.resolve(
    path.dirname(fileURLToPath(import.meta.url)),
    '../../client/dist',
  );
  if (fs.existsSync(clientDist)) {
    app.use(express.static(clientDist));
    app.use((req, res, next) => {
      if (req.path.startsWith('/api')) return next();
      res.sendFile(path.join(clientDist, 'index.html'));
    });
  }

  return app;
}
