/**
 * Coupon Controller
 * API endpoints for coupon management
 *
 * @module BillingUsage
 * @prefix /api/v1/billing/coupons
 */

import { Router, Request, Response, NextFunction } from 'express';
import {
  CouponService,
  CreateCouponDto,
  UpdateCouponDto,
} from '../services/coupon.service';

const router = Router();
const couponService = new CouponService();

/**
 * GET /api/v1/billing/coupons
 * List all coupons
 */
router.get('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { isActive, discountType } = req.query;

    const coupons = await couponService.findAll({
      isActive: isActive === 'true' ? true : isActive === 'false' ? false : undefined,
      discountType: discountType as any,
    });

    return res.json({
      success: true,
      data: coupons,
      count: coupons.length,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/billing/coupons/valid
 * List valid coupons
 */
router.get('/valid', async (_req: Request, res: Response, next: NextFunction) => {
  try {
    const coupons = await couponService.findValidCoupons();

    return res.json({
      success: true,
      data: coupons,
      count: coupons.length,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/billing/coupons/stats
 * Get overall coupon statistics
 */
router.get('/stats', async (_req: Request, res: Response, next: NextFunction) => {
  try {
    const stats = await couponService.getOverallStats();

    return res.json({ success: true, data: stats });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/billing/coupons/generate-code
 * Generate a unique coupon code
 */
router.get('/generate-code', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const prefix = (req.query.prefix as string) || 'PROMO';
    const code = await couponService.generateCode(prefix);

    return res.json({ success: true, data: { code } });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/billing/coupons/my-redemptions
 * Get current tenant's coupon redemptions
 */
router.get('/my-redemptions', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const redemptions = await couponService.getTenantRedemptions({ tenantId });

    return res.json({
      success: true,
      data: redemptions,
      count: redemptions.length,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/billing/coupons/active-redemption
 * Get current tenant's active redemption
 */
router.get('/active-redemption', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const redemption = await couponService.getActiveRedemption({ tenantId });

    if (!redemption) {
      return res.json({ success: true, data: null });
    }

    return res.json({ success: true, data: redemption });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/billing/coupons/:id
 * Get coupon by ID
 */
router.get('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const coupon = await couponService.findById(req.params.id);
    if (!coupon) {
      return res.status(404).json({ error: 'Coupon not found' });
    }

    return res.json({ success: true, data: coupon });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/billing/coupons/:id/stats
 * Get coupon statistics
 */
router.get('/:id/stats', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const coupon = await couponService.findById(req.params.id);
    if (!coupon) {
      return res.status(404).json({ error: 'Coupon not found' });
    }

    const stats = await couponService.getCouponStats(req.params.id);

    return res.json({ success: true, data: stats });
  } catch (error) {
    return next(error);
  }
});

/**
 * GET /api/v1/billing/coupons/:id/redemptions
 * Get coupon redemptions
 */
router.get('/:id/redemptions', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const coupon = await couponService.findById(req.params.id);
    if (!coupon) {
      return res.status(404).json({ error: 'Coupon not found' });
    }

    const redemptions = await couponService.getCouponRedemptions(req.params.id);

    return res.json({
      success: true,
      data: redemptions,
      count: redemptions.length,
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/billing/coupons
 * Create a new coupon
 */
router.post('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const data: CreateCouponDto = req.body;

    if (!data.code || !data.name || !data.discountType || data.discountValue === undefined) {
      return res.status(400).json({
        error: 'code, name, discountType, and discountValue are required',
      });
    }

    // Check if code exists
    const existing = await couponService.findByCode(data.code);
    if (existing) {
      return res.status(409).json({ error: 'A coupon with this code already exists' });
    }

    const coupon = await couponService.create(data);
    return res.status(201).json({ success: true, data: coupon });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/billing/coupons/validate
 * Validate a coupon code
 */
router.post('/validate', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { code, planId, amount } = req.body;

    if (!code || !planId || amount === undefined) {
      return res.status(400).json({ error: 'code, planId, and amount are required' });
    }

    const result = await couponService.validate({ tenantId }, code, planId, amount);

    return res.json({
      success: true,
      data: {
        isValid: result.isValid,
        error: result.error,
        discountAmount: result.discountAmount,
        coupon: result.coupon
          ? {
              id: result.coupon.id,
              code: result.coupon.code,
              name: result.coupon.name,
              discountType: result.coupon.discountType,
              discountValue: result.coupon.discountValue,
            }
          : null,
      },
    });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/billing/coupons/redeem
 * Redeem a coupon
 */
router.post('/redeem', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'X-Tenant-Id header required' });
    }

    const { code, planId, amount, subscriptionId } = req.body;

    if (!code || !planId || amount === undefined) {
      return res.status(400).json({ error: 'code, planId, and amount are required' });
    }

    // Validate first
    const validation = await couponService.validate({ tenantId }, code, planId, amount);
    if (!validation.isValid) {
      return res.status(400).json({ error: validation.error });
    }

    const redemption = await couponService.redeem(
      { tenantId },
      code,
      planId,
      amount,
      subscriptionId
    );

    if (!redemption) {
      return res.status(400).json({ error: 'Failed to redeem coupon' });
    }

    return res.status(201).json({ success: true, data: redemption });
  } catch (error) {
    return next(error);
  }
});

/**
 * PATCH /api/v1/billing/coupons/:id
 * Update a coupon
 */
router.patch('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const data: UpdateCouponDto = req.body;
    const coupon = await couponService.update(req.params.id, data);

    if (!coupon) {
      return res.status(404).json({ error: 'Coupon not found' });
    }

    return res.json({ success: true, data: coupon });
  } catch (error) {
    return next(error);
  }
});

/**
 * POST /api/v1/billing/coupons/:id/deactivate
 * Deactivate a coupon
 */
router.post('/:id/deactivate', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const coupon = await couponService.deactivate(req.params.id);

    if (!coupon) {
      return res.status(404).json({ error: 'Coupon not found' });
    }

    return res.json({ success: true, data: coupon });
  } catch (error) {
    return next(error);
  }
});

/**
 * DELETE /api/v1/billing/coupons/:id
 * Delete a coupon
 */
router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const deleted = await couponService.delete(req.params.id);
    if (!deleted) {
      return res.status(404).json({ error: 'Coupon not found' });
    }

    return res.json({ success: true, message: 'Coupon deleted' });
  } catch (error) {
    return next(error);
  }
});

export default router;
