const express = require('express');
const { v4: uuidv4 } = require('uuid');
const router = express.Router();

module.exports = (pool, query, authMiddleware) => {
  // Apply authentication middleware to all routes
  router.use(authMiddleware);
  
  /**
   * GET /api/admin/coupons
   * Get all coupons
   */
  router.get('/', async (req, res, next) => {
    try {
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Get all coupons with category and tag information
      const result = await query(`
        SELECT c.*, 
          (
            SELECT json_agg(
              json_build_object(
                'id', pc.id,
                'name', pc.name
              )
            )
            FROM coupon_categories cc
            JOIN product_categories pc ON cc.category_id = pc.id
            WHERE cc.coupon_id = c.id
          ) AS categories,
          (
            SELECT json_agg(
              json_build_object(
                'id', t.id,
                'name', t.name
              )
            )
            FROM coupon_tags ct
            JOIN tags t ON ct.tag_id = t.id
            WHERE ct.coupon_id = c.id
          ) AS tags,
          (
            SELECT COUNT(*)
            FROM coupon_redemptions cr
            WHERE cr.coupon_id = c.id
          ) AS redemption_count
        FROM coupons c
        ORDER BY c.created_at DESC
      `);
      
      res.json(result.rows);
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * GET /api/admin/coupons/:id
   * Get single coupon by ID
   */
  router.get('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Get coupon with categories, tags, and blacklisted products
      const result = await query(`
        SELECT c.*, 
          (
            SELECT json_agg(
              json_build_object(
                'id', pc.id,
                'name', pc.name
              )
            )
            FROM coupon_categories cc
            JOIN product_categories pc ON cc.category_id = pc.id
            WHERE cc.coupon_id = c.id
          ) AS categories,
          (
            SELECT json_agg(
              json_build_object(
                'id', t.id,
                'name', t.name
              )
            )
            FROM coupon_tags ct
            JOIN tags t ON ct.tag_id = t.id
            WHERE ct.coupon_id = c.id
          ) AS tags,
          (
            SELECT json_agg(
              json_build_object(
                'id', p.id,
                'name', p.name
              )
            )
            FROM coupon_blacklist bl
            JOIN products p ON bl.product_id = p.id
            WHERE bl.coupon_id = c.id
          ) AS blacklisted_products
        FROM coupons c
        WHERE c.id = $1
      `, [id]);
      
      if (result.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Coupon not found'
        });
      }
      
      res.json(result.rows[0]);
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * POST /api/admin/coupons
   * Create a new coupon
   */
  router.post('/', async (req, res, next) => {
    try {
      const {
        code,
        description,
        discountType,
        discountValue,
        minPurchaseAmount,
        maxDiscountAmount,
        redemptionLimit,
        startDate,
        endDate,
        isActive,
        categories,
        tags,
        blacklistedProducts
      } = req.body;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate required fields
      if (!code || !discountType || !discountValue) {
        return res.status(400).json({
          error: true,
          message: 'Code, discount type, and discount value are required'
        });
      }
      
      // Validate discount type
      if (!['percentage', 'fixed_amount'].includes(discountType)) {
        return res.status(400).json({
          error: true,
          message: 'Discount type must be either "percentage" or "fixed_amount"'
        });
      }
      
      // Validate discount value
      if (discountType === 'percentage' && (discountValue <= 0 || discountValue > 100)) {
        return res.status(400).json({
          error: true,
          message: 'Percentage discount must be between 0 and 100'
        });
      }
      
      if (discountType === 'fixed_amount' && discountValue <= 0) {
        return res.status(400).json({
          error: true,
          message: 'Fixed amount discount must be greater than 0'
        });
      }
      
      // Check if code is already used
      const existingCoupon = await query(
        'SELECT * FROM coupons WHERE code = $1',
        [code]
      );
      
      if (existingCoupon.rows.length > 0) {
        return res.status(400).json({
          error: true,
          message: 'Coupon code already exists'
        });
      }
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Create coupon
        const couponResult = await client.query(`
          INSERT INTO coupons (
            id, code, description, discount_type, discount_value, 
            min_purchase_amount, max_discount_amount, redemption_limit,
            start_date, end_date, is_active
          ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
          RETURNING *
        `, [
          uuidv4(),
          code,
          description || null,
          discountType,
          discountValue,
          minPurchaseAmount || null,
          maxDiscountAmount || null,
          redemptionLimit || null,
          startDate || null,
          endDate || null,
          isActive !== undefined ? isActive : true
        ]);
        
        const couponId = couponResult.rows[0].id;
        
        // Add categories if provided
        if (categories && categories.length > 0) {
          for (const categoryId of categories) {
            await client.query(
              'INSERT INTO coupon_categories (coupon_id, category_id) VALUES ($1, $2)',
              [couponId, categoryId]
            );
          }
        }
        
        // Add tags if provided
        if (tags && tags.length > 0) {
          for (const tagId of tags) {
            await client.query(
              'INSERT INTO coupon_tags (coupon_id, tag_id) VALUES ($1, $2)',
              [couponId, tagId]
            );
          }
        }
        
        // Add blacklisted products if provided
        if (blacklistedProducts && blacklistedProducts.length > 0) {
          for (const productId of blacklistedProducts) {
            await client.query(
              'INSERT INTO coupon_blacklist (coupon_id, product_id) VALUES ($1, $2)',
              [couponId, productId]
            );
          }
        }
        
        await client.query('COMMIT');
        
        // Get the complete coupon data
        const result = await query(`
          SELECT c.*, 
            (
              SELECT json_agg(
                json_build_object(
                  'id', pc.id,
                  'name', pc.name
                )
              )
              FROM coupon_categories cc
              JOIN product_categories pc ON cc.category_id = pc.id
              WHERE cc.coupon_id = c.id
            ) AS categories,
            (
              SELECT json_agg(
                json_build_object(
                  'id', t.id,
                  'name', t.name
                )
              )
              FROM coupon_tags ct
              JOIN tags t ON ct.tag_id = t.id
              WHERE ct.coupon_id = c.id
            ) AS tags,
            (
              SELECT json_agg(
                json_build_object(
                  'id', p.id,
                  'name', p.name
                )
              )
              FROM coupon_blacklist bl
              JOIN products p ON bl.product_id = p.id
              WHERE bl.coupon_id = c.id
            ) AS blacklisted_products
          FROM coupons c
          WHERE c.id = $1
        `, [couponId]);
        
        res.status(201).json({
          message: 'Coupon created successfully',
          coupon: result.rows[0]
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * PUT /api/admin/coupons/:id
   * Update a coupon
   */
  router.put('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      const {
        code,
        description,
        discountType,
        discountValue,
        minPurchaseAmount,
        maxDiscountAmount,
        redemptionLimit,
        startDate,
        endDate,
        isActive,
        categories,
        tags,
        blacklistedProducts
      } = req.body;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Check if coupon exists
      const couponCheck = await query(
        'SELECT * FROM coupons WHERE id = $1',
        [id]
      );
      
      if (couponCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Coupon not found'
        });
      }
      
      // Validate discount type if provided
      if (discountType && !['percentage', 'fixed_amount'].includes(discountType)) {
        return res.status(400).json({
          error: true,
          message: 'Discount type must be either "percentage" or "fixed_amount"'
        });
      }
      
      // Validate discount value if provided
      if (discountType === 'percentage' && discountValue !== undefined && (discountValue <= 0 || discountValue > 100)) {
        return res.status(400).json({
          error: true,
          message: 'Percentage discount must be between 0 and 100'
        });
      }
      
      if (discountType === 'fixed_amount' && discountValue !== undefined && discountValue <= 0) {
        return res.status(400).json({
          error: true,
          message: 'Fixed amount discount must be greater than 0'
        });
      }
      
      // Check if new code conflicts with existing coupons
      if (code && code !== couponCheck.rows[0].code) {
        const codeCheck = await query(
          'SELECT * FROM coupons WHERE code = $1 AND id != $2',
          [code, id]
        );
        
        if (codeCheck.rows.length > 0) {
          return res.status(400).json({
            error: true,
            message: 'Coupon code already exists'
          });
        }
      }
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Update coupon
        const updateFields = [];
        const updateValues = [];
        let paramIndex = 1;
        
        if (code !== undefined) {
          updateFields.push(`code = $${paramIndex}`);
          updateValues.push(code);
          paramIndex++;
        }
        
        if (description !== undefined) {
          updateFields.push(`description = $${paramIndex}`);
          updateValues.push(description);
          paramIndex++;
        }
        
        if (discountType !== undefined) {
          updateFields.push(`discount_type = $${paramIndex}`);
          updateValues.push(discountType);
          paramIndex++;
        }
        
        if (discountValue !== undefined) {
          updateFields.push(`discount_value = $${paramIndex}`);
          updateValues.push(discountValue);
          paramIndex++;
        }
        
        if (minPurchaseAmount !== undefined) {
          updateFields.push(`min_purchase_amount = $${paramIndex}`);
          updateValues.push(minPurchaseAmount);
          paramIndex++;
        }
        
        if (maxDiscountAmount !== undefined) {
          updateFields.push(`max_discount_amount = $${paramIndex}`);
          updateValues.push(maxDiscountAmount);
          paramIndex++;
        }
        
        if (redemptionLimit !== undefined) {
          updateFields.push(`redemption_limit = $${paramIndex}`);
          updateValues.push(redemptionLimit);
          paramIndex++;
        }
        
        if (startDate !== undefined) {
          updateFields.push(`start_date = $${paramIndex}`);
          updateValues.push(startDate);
          paramIndex++;
        }
        
        if (endDate !== undefined) {
          updateFields.push(`end_date = $${paramIndex}`);
          updateValues.push(endDate);
          paramIndex++;
        }
        
        if (isActive !== undefined) {
          updateFields.push(`is_active = $${paramIndex}`);
          updateValues.push(isActive);
          paramIndex++;
        }
        
        // Only update if there are fields to update
        if (updateFields.length > 0) {
          updateValues.push(id);
          await client.query(`
            UPDATE coupons 
            SET ${updateFields.join(', ')} 
            WHERE id = $${paramIndex}
          `, updateValues);
        }
        
        // Update categories if provided
        if (categories !== undefined) {
          // Remove existing categories
          await client.query(
            'DELETE FROM coupon_categories WHERE coupon_id = $1',
            [id]
          );
          
          // Add new categories
          if (categories && categories.length > 0) {
            for (const categoryId of categories) {
              await client.query(
                'INSERT INTO coupon_categories (coupon_id, category_id) VALUES ($1, $2)',
                [id, categoryId]
              );
            }
          }
        }
        
        // Update tags if provided
        if (tags !== undefined) {
          // Remove existing tags
          await client.query(
            'DELETE FROM coupon_tags WHERE coupon_id = $1',
            [id]
          );
          
          // Add new tags
          if (tags && tags.length > 0) {
            for (const tagId of tags) {
              await client.query(
                'INSERT INTO coupon_tags (coupon_id, tag_id) VALUES ($1, $2)',
                [id, tagId]
              );
            }
          }
        }
        
        // Update blacklisted products if provided
        if (blacklistedProducts !== undefined) {
          // Remove existing blacklisted products
          await client.query(
            'DELETE FROM coupon_blacklist WHERE coupon_id = $1',
            [id]
          );
          
          // Add new blacklisted products
          if (blacklistedProducts && blacklistedProducts.length > 0) {
            for (const productId of blacklistedProducts) {
              await client.query(
                'INSERT INTO coupon_blacklist (coupon_id, product_id) VALUES ($1, $2)',
                [id, productId]
              );
            }
          }
        }
        
        await client.query('COMMIT');
        
        // Get the updated coupon data
        const result = await query(`
          SELECT c.*, 
            (
              SELECT json_agg(
                json_build_object(
                  'id', pc.id,
                  'name', pc.name
                )
              )
              FROM coupon_categories cc
              JOIN product_categories pc ON cc.category_id = pc.id
              WHERE cc.coupon_id = c.id
            ) AS categories,
            (
              SELECT json_agg(
                json_build_object(
                  'id', t.id,
                  'name', t.name
                )
              )
              FROM coupon_tags ct
              JOIN tags t ON ct.tag_id = t.id
              WHERE ct.coupon_id = c.id
            ) AS tags,
            (
              SELECT json_agg(
                json_build_object(
                  'id', p.id,
                  'name', p.name
                )
              )
              FROM coupon_blacklist bl
              JOIN products p ON bl.product_id = p.id
              WHERE bl.coupon_id = c.id
            ) AS blacklisted_products
          FROM coupons c
          WHERE c.id = $1
        `, [id]);
        
        res.json({
          message: 'Coupon updated successfully',
          coupon: result.rows[0]
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * DELETE /api/admin/coupons/:id
   * Delete a coupon
   */
  router.delete('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Check if coupon exists
      const couponCheck = await query(
        'SELECT * FROM coupons WHERE id = $1',
        [id]
      );
      
      if (couponCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Coupon not found'
        });
      }
      
      // Delete coupon (cascade will handle related records)
      await query(
        'DELETE FROM coupons WHERE id = $1',
        [id]
      );
      
      res.json({
        message: 'Coupon deleted successfully'
      });
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * GET /api/admin/coupons/:id/redemptions
   * Get coupon redemption history
   */
  router.get('/:id/redemptions', async (req, res, next) => {
    try {
      const { id } = req.params;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Check if coupon exists
      const couponCheck = await query(
        'SELECT * FROM coupons WHERE id = $1',
        [id]
      );
      
      if (couponCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Coupon not found'
        });
      }
      
      // Get redemption history
      const result = await query(`
        SELECT cr.*, u.email, u.first_name, u.last_name, o.total_amount
        FROM coupon_redemptions cr
        JOIN users u ON cr.user_id = u.id
        JOIN orders o ON cr.order_id = o.id
        WHERE cr.coupon_id = $1
        ORDER BY cr.redeemed_at DESC
      `, [id]);
      
      res.json(result.rows);
    } catch (error) {
      next(error);
    }
  });
  
  return router;
};