/**
 * Admin Payment Routes
 * Purpose: Admin management of payment methods and deposits
 * Routes: Payment method CRUD, deposit approval/rejection
 */

const express = require('express');
const router = express.Router();
const { authenticateToken, requireAdmin } = require('../middleware/authMiddleware');

/**
 * GET /api/admin/payment-methods
 * Get all payment methods (including inactive)
 */
router.get('/payment-methods', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');

  try {
    const [methods] = await pool.execute(
      `SELECT
        pm.*,
        (SELECT COUNT(*) FROM deposits WHERE payment_method_id = pm.id) as total_deposits,
        (SELECT SUM(amount) FROM deposits WHERE payment_method_id = pm.id AND status = 'completed') as total_amount,
        (SELECT COUNT(*) FROM deposits WHERE payment_method_id = pm.id AND status = 'completed') as successful_deposits
      FROM payment_methods pm
      ORDER BY display_order ASC, name ASC`
    );

    res.json({
      success: true,
      data: methods
    });
  } catch (error) {
    console.error('Get payment methods error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to retrieve payment methods'
    });
  }
});

/**
 * GET /api/admin/payment-methods/:id
 * Get payment method details
 */
router.get('/payment-methods/:id', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');
  const { id } = req.params;

  try {
    const [methods] = await pool.execute(
      'SELECT * FROM payment_methods WHERE id = ?',
      [id]
    );

    if (methods.length === 0) {
      return res.status(404).json({
        success: false,
        message: 'Payment method not found'
      });
    }

    res.json({
      success: true,
      data: methods[0]
    });
  } catch (error) {
    console.error('Get payment method error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to retrieve payment method'
    });
  }
});

/**
 * POST /api/admin/payment-methods
 * Create new payment method
 */
router.post('/payment-methods', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');
  const {
    name,
    code,
    type,
    logo_url,
    description,
    transaction_fee_percentage,
    transaction_fee_fixed,
    transaction_fee_cap,
    min_amount,
    max_amount,
    is_active,
    is_automated,
    requires_proof,
    processing_time_minutes,
    config,
    instructions,
    display_order
  } = req.body;

  try {
    // Check if code already exists
    const [existing] = await pool.execute(
      'SELECT id FROM payment_methods WHERE code = ?',
      [code]
    );

    if (existing.length > 0) {
      return res.status(400).json({
        success: false,
        message: 'Payment method with this code already exists'
      });
    }

    const [result] = await pool.execute(
      `INSERT INTO payment_methods (
        name,
        code,
        type,
        logo_url,
        description,
        transaction_fee_percentage,
        transaction_fee_fixed,
        transaction_fee_cap,
        min_amount,
        max_amount,
        is_active,
        is_automated,
        requires_proof,
        processing_time_minutes,
        config,
        instructions,
        display_order,
        created_at,
        updated_at
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`,
      [
        name,
        code,
        type,
        logo_url,
        description,
        transaction_fee_percentage || 0,
        transaction_fee_fixed || 0,
        transaction_fee_cap,
        min_amount || 100,
        max_amount || 1000000,
        is_active !== false,
        is_automated || false,
        requires_proof || false,
        processing_time_minutes || 0,
        config ? JSON.stringify(config) : null,
        instructions,
        display_order || 0
      ]
    );

    res.status(201).json({
      success: true,
      data: {
        id: result.insertId
      },
      message: 'Payment method created successfully'
    });
  } catch (error) {
    console.error('Create payment method error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to create payment method'
    });
  }
});

/**
 * PUT /api/admin/payment-methods/:id
 * Update payment method
 */
router.put('/payment-methods/:id', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');
  const { id } = req.params;
  const {
    name,
    logo_url,
    description,
    transaction_fee_percentage,
    transaction_fee_fixed,
    transaction_fee_cap,
    min_amount,
    max_amount,
    is_active,
    is_automated,
    requires_proof,
    processing_time_minutes,
    config,
    instructions,
    display_order
  } = req.body;

  try {
    const [existing] = await pool.execute(
      'SELECT id FROM payment_methods WHERE id = ?',
      [id]
    );

    if (existing.length === 0) {
      return res.status(404).json({
        success: false,
        message: 'Payment method not found'
      });
    }

    await pool.execute(
      `UPDATE payment_methods SET
        name = ?,
        logo_url = ?,
        description = ?,
        transaction_fee_percentage = ?,
        transaction_fee_fixed = ?,
        transaction_fee_cap = ?,
        min_amount = ?,
        max_amount = ?,
        is_active = ?,
        is_automated = ?,
        requires_proof = ?,
        processing_time_minutes = ?,
        config = ?,
        instructions = ?,
        display_order = ?,
        updated_at = NOW()
      WHERE id = ?`,
      [
        name,
        logo_url,
        description,
        transaction_fee_percentage,
        transaction_fee_fixed,
        transaction_fee_cap,
        min_amount,
        max_amount,
        is_active,
        is_automated,
        requires_proof,
        processing_time_minutes,
        config ? JSON.stringify(config) : null,
        instructions,
        display_order,
        id
      ]
    );

    res.json({
      success: true,
      message: 'Payment method updated successfully'
    });
  } catch (error) {
    console.error('Update payment method error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to update payment method'
    });
  }
});

/**
 * DELETE /api/admin/payment-methods/:id
 * Delete payment method (soft delete by setting inactive)
 */
router.delete('/payment-methods/:id', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');
  const { id } = req.params;

  try {
    const [existing] = await pool.execute(
      'SELECT id FROM payment_methods WHERE id = ?',
      [id]
    );

    if (existing.length === 0) {
      return res.status(404).json({
        success: false,
        message: 'Payment method not found'
      });
    }

    // Soft delete - just set to inactive
    await pool.execute(
      'UPDATE payment_methods SET is_active = FALSE, updated_at = NOW() WHERE id = ?',
      [id]
    );

    res.json({
      success: true,
      message: 'Payment method deactivated successfully'
    });
  } catch (error) {
    console.error('Delete payment method error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to delete payment method'
    });
  }
});

/**
 * GET /api/admin/deposits
 * Get all deposits (with filters)
 */
router.get('/deposits', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');
  const { page = 1, limit = 50, status, payment_method, user_id, date_from, date_to } = req.query;
  const offset = (page - 1) * limit;

  try {
    let query = `
      SELECT
        d.*,
        u.email as user_email,
        u.username as user_username,
        u.first_name,
        u.last_name,
        pm.name as payment_method_name,
        pm.code as payment_method_code,
        pm.type as payment_method_type,
        v.email as verified_by_email
      FROM deposits d
      JOIN users u ON d.user_id = u.id
      JOIN payment_methods pm ON d.payment_method_id = pm.id
      LEFT JOIN users v ON d.verified_by = v.id
      WHERE 1=1
    `;

    const params = [];

    if (status) {
      query += ' AND d.status = ?';
      params.push(status);
    }

    if (payment_method) {
      query += ' AND pm.code = ?';
      params.push(payment_method);
    }

    if (user_id) {
      query += ' AND d.user_id = ?';
      params.push(user_id);
    }

    if (date_from) {
      query += ' AND d.created_at >= ?';
      params.push(date_from);
    }

    if (date_to) {
      query += ' AND d.created_at <= ?';
      params.push(date_to);
    }

    query += ' ORDER BY d.created_at DESC LIMIT ? OFFSET ?';
    params.push(parseInt(limit), parseInt(offset));

    const [deposits] = await pool.execute(query, params);

    // Get total count
    let countQuery = `
      SELECT COUNT(*) as total
      FROM deposits d
      JOIN payment_methods pm ON d.payment_method_id = pm.id
      WHERE 1=1
    `;
    const countParams = [];

    if (status) {
      countQuery += ' AND d.status = ?';
      countParams.push(status);
    }

    if (payment_method) {
      countQuery += ' AND pm.code = ?';
      countParams.push(payment_method);
    }

    if (user_id) {
      countQuery += ' AND d.user_id = ?';
      countParams.push(user_id);
    }

    if (date_from) {
      countQuery += ' AND d.created_at >= ?';
      countParams.push(date_from);
    }

    if (date_to) {
      countQuery += ' AND d.created_at <= ?';
      countParams.push(date_to);
    }

    const [countResult] = await pool.execute(countQuery, countParams);
    const total = countResult[0].total;

    res.json({
      success: true,
      data: {
        deposits: deposits,
        pagination: {
          page: parseInt(page),
          limit: parseInt(limit),
          total: total,
          total_pages: Math.ceil(total / limit)
        }
      }
    });
  } catch (error) {
    console.error('Get deposits error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to retrieve deposits'
    });
  }
});

/**
 * POST /api/admin/deposits/:id/approve
 * Approve a pending deposit (for manual payment methods)
 */
router.post('/deposits/:id/approve', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');
  const { id } = req.params;
  const { admin_note } = req.body;
  const adminId = req.user.id;

  const connection = await pool.getConnection();
  await connection.beginTransaction();

  try {
    // Get deposit details
    const [deposits] = await connection.execute(
      `SELECT d.*, pm.name as payment_method_name
       FROM deposits d
       JOIN payment_methods pm ON d.payment_method_id = pm.id
       WHERE d.id = ? FOR UPDATE`,
      [id]
    );

    if (deposits.length === 0) {
      await connection.rollback();
      connection.release();
      return res.status(404).json({
        success: false,
        message: 'Deposit not found'
      });
    }

    const deposit = deposits[0];

    if (deposit.status === 'completed') {
      await connection.rollback();
      connection.release();
      return res.status(400).json({
        success: false,
        message: 'Deposit already completed'
      });
    }

    // Get current user balance
    const [users] = await connection.execute(
      'SELECT balance FROM users WHERE id = ?',
      [deposit.user_id]
    );

    const currentBalance = parseFloat(users[0].balance);
    const newBalance = currentBalance + parseFloat(deposit.amount_credited);

    // Update user balance
    await connection.execute(
      'UPDATE users SET balance = ?, updated_at = NOW() WHERE id = ?',
      [newBalance, deposit.user_id]
    );

    // Update deposit
    await connection.execute(
      `UPDATE deposits SET
        status = 'completed',
        admin_note = ?,
        verified_by = ?,
        verified_at = NOW(),
        completed_at = NOW(),
        updated_at = NOW()
      WHERE id = ?`,
      [admin_note, adminId, id]
    );

    // Create transaction record
    await connection.execute(
      `INSERT INTO transactions (
        user_id,
        deposit_id,
        type,
        amount,
        post_balance,
        status,
        description,
        reference,
        created_at,
        updated_at
      ) VALUES (?, ?, 'credit', ?, ?, 'completed', ?, ?, NOW(), NOW())`,
      [
        deposit.user_id,
        deposit.id,
        deposit.amount_credited,
        newBalance,
        `Deposit via ${deposit.payment_method_name} (Admin Approved)`,
        deposit.reference
      ]
    );

    await connection.commit();
    connection.release();

    res.json({
      success: true,
      message: 'Deposit approved and credited successfully',
      data: {
        amount_credited: deposit.amount_credited,
        new_balance: newBalance
      }
    });
  } catch (error) {
    await connection.rollback();
    connection.release();
    console.error('Approve deposit error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to approve deposit'
    });
  }
});

/**
 * POST /api/admin/deposits/:id/reject
 * Reject a pending deposit
 */
router.post('/deposits/:id/reject', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');
  const { id } = req.params;
  const { admin_note } = req.body;
  const adminId = req.user.id;

  try {
    const [deposits] = await pool.execute(
      'SELECT * FROM deposits WHERE id = ?',
      [id]
    );

    if (deposits.length === 0) {
      return res.status(404).json({
        success: false,
        message: 'Deposit not found'
      });
    }

    const deposit = deposits[0];

    if (deposit.status === 'completed') {
      return res.status(400).json({
        success: false,
        message: 'Cannot reject completed deposit'
      });
    }

    await pool.execute(
      `UPDATE deposits SET
        status = 'rejected',
        admin_note = ?,
        verified_by = ?,
        verified_at = NOW(),
        updated_at = NOW()
      WHERE id = ?`,
      [admin_note, adminId, id]
    );

    res.json({
      success: true,
      message: 'Deposit rejected successfully'
    });
  } catch (error) {
    console.error('Reject deposit error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to reject deposit'
    });
  }
});

/**
 * GET /api/admin/deposits/stats
 * Get deposit statistics
 */
router.get('/deposits/stats', authenticateToken, requireAdmin, async (req, res) => {
  const pool = req.app.get('pool');
  const { date_from, date_to } = req.query;

  try {
    let dateFilter = '';
    const params = [];

    if (date_from) {
      dateFilter += ' AND created_at >= ?';
      params.push(date_from);
    }

    if (date_to) {
      dateFilter += ' AND created_at <= ?';
      params.push(date_to);
    }

    // Overall stats
    const [overallStats] = await pool.execute(
      `SELECT
        COUNT(*) as total_deposits,
        SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_deposits,
        SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending_deposits,
        SUM(CASE WHEN status = 'awaiting_proof' THEN 1 ELSE 0 END) as awaiting_proof_deposits,
        SUM(CASE WHEN status = 'rejected' THEN 1 ELSE 0 END) as rejected_deposits,
        SUM(CASE WHEN status = 'completed' THEN amount ELSE 0 END) as total_amount,
        SUM(CASE WHEN status = 'completed' THEN fee ELSE 0 END) as total_fees,
        SUM(CASE WHEN status = 'completed' THEN amount_credited ELSE 0 END) as total_credited
      FROM deposits
      WHERE 1=1 ${dateFilter}`,
      params
    );

    // Stats by payment method
    const [methodStats] = await pool.execute(
      `SELECT
        pm.name as payment_method,
        pm.code as payment_method_code,
        COUNT(*) as total_deposits,
        SUM(CASE WHEN d.status = 'completed' THEN 1 ELSE 0 END) as completed_deposits,
        SUM(CASE WHEN d.status = 'completed' THEN d.amount ELSE 0 END) as total_amount
      FROM deposits d
      JOIN payment_methods pm ON d.payment_method_id = pm.id
      WHERE 1=1 ${dateFilter}
      GROUP BY pm.id
      ORDER BY total_amount DESC`,
      params
    );

    res.json({
      success: true,
      data: {
        overall: overallStats[0],
        by_method: methodStats
      }
    });
  } catch (error) {
    console.error('Get deposit stats error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to retrieve deposit statistics'
    });
  }
});

module.exports = router;
