import { Router, Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import rateLimit from 'express-rate-limit';
import RedisStore from 'rate-limit-redis';
import { redis } from '../../config/redis';
import { env } from '../../config/env';
import { listmonkClient } from '../../services/listmonk.client';
import { logger } from '../../utils/logger';

const router = Router();

const subscribeRateLimit = rateLimit({
  windowMs: 60 * 1000,
  max: 5,
  standardHeaders: true,
  legacyHeaders: false,
  store: new RedisStore({
    sendCommand: (command: string, ...args: string[]) => redis.call(command, ...args) as Promise<any>,
    prefix: 'rl:newsletter-subscribe:',
  }),
  message: { error: { message: 'Too many subscribe attempts, please try again later', code: 'NEWSLETTER_RATE_LIMIT_EXCEEDED' } },
});

const subscribeSchema = z.object({
  email: z.string().email(),
  name: z.string().optional(),
});

const PUBLIC_LIST_NAME = 'Public Updates';

// POST /api/newsletter/subscribe
router.post('/subscribe', subscribeRateLimit, async (req: Request, res: Response, next: NextFunction) => {
  try {
    // Check if Listmonk is enabled
    if (env.LISTMONK_SYNC_ENABLED !== 'true') {
      res.status(503).json({ error: { message: 'Newsletter subscriptions are not currently available' } });
      return;
    }

    const body = subscribeSchema.parse(req.body);

    // Find or create the "Public Updates" list
    let lists = await listmonkClient.getLists();
    let publicList = lists.find(l => l.name === PUBLIC_LIST_NAME);
    if (!publicList) {
      publicList = await listmonkClient.createList(PUBLIC_LIST_NAME, 'public', ['public', 'auto']);
    }

    // Create or update subscriber (double opt-in via Listmonk's optin flow)
    try {
      await listmonkClient.createSubscriber(
        body.email,
        body.name || '',
        [publicList.id],
        { source: 'public_signup' },
      );
    } catch (err: any) {
      // If subscriber already exists, that's fine
      if (err?.message?.includes('already exists') || err?.statusCode === 409) {
        // subscriber already exists, success
      } else {
        throw err;
      }
    }

    res.json({ success: true, message: 'Check your email to confirm your subscription' });
  } catch (err) {
    if (err instanceof z.ZodError) {
      res.status(400).json({ error: { message: 'Please provide a valid email address' } });
      return;
    }
    logger.error('Newsletter subscribe error:', err);
    next(err);
  }
});

export { router as newsletterPublicRouter };
