import { Router } from 'express';
import rateLimit from 'express-rate-limit';
import { z } from 'zod';
import type { DatabaseSync } from 'node:sqlite';
import { requireAuth } from '../middleware/auth.ts';
import {
  addSubscription,
  removeSubscription,
  listUserSubscriptions,
  userOwnsSubscription,
} from '../services/subscriptions.ts';
import type { UrlGuard } from '../services/ingest.ts';

const bodySchema = z.object({ url: z.string().url() });

type SubscriptionBody = z.infer<typeof bodySchema>;

export function createSubscriptionsRouter(db: DatabaseSync, guard?: UrlGuard): Router {
  const router = Router();
  const subLimiter = rateLimit({
    windowMs: 15 * 60 * 1000,
    max: 30,
    standardHeaders: true,
    legacyHeaders: false,
  });
  router.use(requireAuth);

  router.get('/', (req, res) => {
    const subs = listUserSubscriptions(db, req.session.userId!);
    res.json(
      subs.map((s) => ({
        id: s.feed_id,
        url: s.url,
        title: s.title,
        createdAt: s.created_at,
      })),
    );
  });

  router.post('/', subLimiter, async (req, res) => {
    try {
      const body: SubscriptionBody = bodySchema.parse(req.body);
      const feed = await addSubscription(db, req.session.userId!, body.url, guard);
      if (!feed) return res.status(400).json({ error: 'could not resolve feed' });
      res.status(201).json({ id: feed.id, url: feed.url, title: feed.title });
    } 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.delete('/:id', (req, res) => {
    const feedId = Number(req.params.id);
    if (!userOwnsSubscription(db, req.session.userId!, feedId)) {
      return res.status(404).json({ error: 'not found' });
    }
    removeSubscription(db, req.session.userId!, feedId);
    res.status(204).end();
  });

  return router;
}
