import { Router } from 'express';
import rateLimit from 'express-rate-limit';
import { z } from 'zod';
import type { DatabaseSync } from 'node:sqlite';
import { registerUser, verifyUser, getUser } from '../services/auth.ts';

const registerSchema = z.object({ email: z.string().email(), password: z.string().min(8) });
const loginSchema = z.object({ email: z.string().email(), password: z.string().min(1) });

type RegisterBody = z.infer<typeof registerSchema>;
type LoginBody = z.infer<typeof loginSchema>;

export function createAuthRouter(db: DatabaseSync): Router {
  const router = Router();
  // Only throttle credential creation/checking. /me and /logout are called on
  // every page load and must never be rate-limited into a fake "logged out" state.
  const authLimiter = rateLimit({
    windowMs: 15 * 60 * 1000,
    max: 10,
    standardHeaders: true,
    legacyHeaders: false,
  });

  router.post('/register', authLimiter, async (req, res, _next) => {
    try {
      const body: RegisterBody = registerSchema.parse(req.body);
      const user = await registerUser(db, body.email, body.password);
      if (!user) return res.status(400).json({ error: 'registration failed' });
      req.session.userId = user.id;
      res.status(201).json({ id: user.id, email: user.email });
    } catch (e) {
      if (e instanceof z.ZodError) return res.status(400).json({ error: e.errors });
      res.status(400).json({ error: e instanceof Error ? e.message : String(e) });
    }
  });

  router.post('/login', authLimiter, async (req, res) => {
    try {
      const body: LoginBody = loginSchema.parse(req.body);
      const user = await verifyUser(db, body.email, body.password);
      if (!user) return res.status(401).json({ error: 'invalid credentials' });
      req.session.userId = user.id;
      res.json({ id: user.id, email: user.email });
    } catch (e) {
      if (e instanceof z.ZodError) return res.status(400).json({ error: e.errors });
      res.status(400).json({ error: e instanceof Error ? e.message : String(e) });
    }
  });

  router.post('/logout', (req, res) => {
    req.session.destroy(() => {
      res.clearCookie('connect.sid');
      res.status(204).end();
    });
  });

  router.get('/me', (req, res) => {
    if (!req.session?.userId) return res.status(401).json({ error: 'authentication required' });
    const user = getUser(db, req.session.userId);
    if (!user) return res.status(401).json({ error: 'authentication required' });
    res.json({ id: user.id, email: user.email });
  });

  return router;
}
