import { Router, Request, Response, NextFunction } from 'express';
import { getPublishableKey } from '../../services/stripe.client';
import { paymentSettingsService, requirePaymentsEnabled } from './payment-settings.service';
import { subscriptionsService } from './subscriptions.service';
import { plansService } from './plans.service';
import { productsService } from './products.service';
import { donationsService } from './donations.service';
import { authenticate } from '../../middleware/auth.middleware';
import { validate } from '../../middleware/validate';
import { paymentCheckoutRateLimit } from '../../middleware/rate-limit';
import {
  createSubscriptionCheckoutSchema,
  createProductCheckoutSchema,
  createDonationCheckoutSchema,
} from './payments.schemas';

const router = Router();

// GET /api/payments/config — public payment config (publishable key, donation settings)
router.get('/config', async (_req: Request, res: Response, next: NextFunction) => {
  try {
    const publishableKey = await getPublishableKey();
    const settings = await paymentSettingsService.getPublic();
    res.json({
      publishableKey,
      defaultCurrency: settings.defaultCurrency,
      enableDonations: settings.enableDonations,
      donationSuggestedAmounts: settings.donationSuggestedAmounts,
      donationMinimum: settings.donationMinimum,
      donationPageTitle: settings.donationPageTitle,
      donationPageDescription: settings.donationPageDescription,
      thankYouMessage: settings.thankYouMessage,
    });
  } catch (err) {
    next(err);
  }
});

// GET /api/payments/plans?limit=50 — list active subscription plans
router.get('/plans', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const limit = Math.min(parseInt(req.query.limit as string) || 50, 100);
    const plans = await plansService.listActivePlans(limit);
    res.json(plans);
  } catch (err) {
    next(err);
  }
});

// GET /api/payments/plans/:slug — public plan detail by slug
router.get('/plans/:slug', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const slug = req.params.slug as string;
    const plan = await plansService.findBySlugPublic(slug);
    res.json(plan);
  } catch (err) {
    next(err);
  }
});

// GET /api/payments/products?page=1&limit=20 — list active products (paginated)
router.get('/products', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const type = req.query.type as string | undefined;
    const page = Math.max(parseInt(req.query.page as string) || 1, 1);
    const limit = Math.min(parseInt(req.query.limit as string) || 20, 50);
    const result = await productsService.listActive(type, page, limit);
    res.json(result);
  } catch (err) {
    next(err);
  }
});

// GET /api/payments/products/:slug — single active product by slug (detail page)
router.get('/products/:slug', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const slug = req.params.slug as string;
    const product = await productsService.getBySlug(slug);
    if (!product) {
      res.status(404).json({ error: { message: 'Product not found', code: 'NOT_FOUND' } });
      return;
    }
    res.json(product);
  } catch (err) {
    next(err);
  }
});

// POST /api/payments/subscribe — create subscription checkout (requires login)
router.post(
  '/subscribe',
  requirePaymentsEnabled,
  paymentCheckoutRateLimit,
  authenticate,
  validate(createSubscriptionCheckoutSchema),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { planId, frequency } = req.body;
      const result = await subscriptionsService.createCheckoutSession(
        req.user!.id,
        planId,
        frequency,
      );
      res.json(result);
    } catch (err) {
      next(err);
    }
  }
);

// POST /api/payments/purchase — create product checkout (guest or logged-in)
router.post(
  '/purchase',
  requirePaymentsEnabled,
  paymentCheckoutRateLimit,
  validate(createProductCheckoutSchema),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { productId, buyerEmail, buyerName } = req.body;
      // Try to get user ID from optional auth
      const userId = req.user?.id;
      const result = await productsService.createProductCheckout(productId, buyerEmail, buyerName, userId);
      res.json(result);
    } catch (err) {
      next(err);
    }
  }
);

// POST /api/payments/donate — create donation checkout (no auth required)
router.post(
  '/donate',
  requirePaymentsEnabled,
  paymentCheckoutRateLimit,
  validate(createDonationCheckoutSchema),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { amountCents, email, name, message, isAnonymous, campaignId } = req.body;
      const result = await donationsService.createDonationCheckout(
        amountCents,
        email,
        name,
        message,
        isAnonymous,
        undefined, // donationPageId
        undefined, // donationPageSlug
        undefined, // donationPageTitle
        campaignId,
      );
      res.json(result);
    } catch (err) {
      next(err);
    }
  }
);

// GET /api/payments/my-subscription — current user's subscription
router.get(
  '/my-subscription',
  authenticate,
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const sub = await subscriptionsService.getActiveSubscription(req.user!.id);
      res.json(sub || { status: 'none' });
    } catch (err) {
      next(err);
    }
  }
);

// POST /api/payments/my-subscription/cancel — cancel own subscription
router.post(
  '/my-subscription/cancel',
  authenticate,
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const sub = await subscriptionsService.getActiveSubscription(req.user!.id);
      if (!sub) {
        res.status(404).json({ error: { message: 'No active subscription', code: 'NOT_FOUND' } });
        return;
      }
      const updated = await subscriptionsService.cancelSubscription(sub.id);
      res.json(updated);
    } catch (err) {
      next(err);
    }
  }
);

export { router as paymentsPublicRouter };
