/**
 * Deposit Routes
 * Purpose: User deposit/payment endpoints
 * Routes: Deposit initialization, verification, history
 */

const express = require('express');
const router = express.Router();
const { authenticateToken } = require('../middleware/authMiddleware');
const { getPaymentServiceFactory } = require('../services/payments');

/**
 * GET /api/deposits/methods
 * Get all available payment methods
 */
router.get('/methods', authenticateToken, async (req, res) => {
  const pool = req.app.get('pool');

  try {
    const [methods] = await pool.execute(
      `SELECT
        id,
        name,
        code,
        type,
        logo_url,
        description,
        transaction_fee_percentage,
        transaction_fee_fixed,
        transaction_fee_cap,
        min_amount,
        max_amount,
        is_automated,
        requires_proof,
        processing_time_minutes,
        instructions,
        display_order
      FROM payment_methods
      WHERE is_active = TRUE
      ORDER BY display_order ASC, name ASC`
    );

    // Calculate fees for each method (example for ₦1000)
    const methodsWithFees = methods.map(method => {
      const exampleAmount = 1000;
      const percentageFee = (exampleAmount * method.transaction_fee_percentage) / 100;
      const totalFee = Math.min(
        percentageFee + method.transaction_fee_fixed,
        method.transaction_fee_cap || Infinity
      );

      return {
        ...method,
        example_fee: totalFee,
        example_total: exampleAmount + totalFee
      };
    });

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

/**
 * POST /api/deposits/initialize
 * Initialize a new deposit
 */
router.post('/initialize', authenticateToken, async (req, res) => {
  const pool = req.app.get('pool');
  const userId = req.user.userId; // Fixed: JWT uses userId not id
  const { payment_method_id, amount } = req.body;

  try {
    // Validate input
    if (!payment_method_id || !amount) {
      return res.status(400).json({
        success: false,
        message: 'Payment method and amount are required'
      });
    }

    if (amount < 100 || amount > 1000000) {
      return res.status(400).json({
        success: false,
        message: 'Amount must be between ₦100 and ₦1,000,000'
      });
    }

    // Get payment method details
    const [methods] = await pool.execute(
      `SELECT * FROM payment_methods WHERE id = ? AND is_active = TRUE`,
      [payment_method_id]
    );

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

    const method = methods[0];

    // Validate amount limits
    if (amount < method.min_amount || amount > method.max_amount) {
      return res.status(400).json({
        success: false,
        message: `Amount must be between ₦${method.min_amount} and ₦${method.max_amount} for ${method.name}`
      });
    }

    // Calculate fees
    const percentageFee = (amount * method.transaction_fee_percentage) / 100;
    const totalFee = Math.min(
      percentageFee + method.transaction_fee_fixed,
      method.transaction_fee_cap || Infinity
    );
    const amountCredited = amount - totalFee;

    // Generate unique reference
    const reference = `WAKA_${userId}_${Date.now()}`;

    // Get user details
    const [users] = await pool.execute(
      'SELECT id, email, first_name, last_name, mobile_number FROM users WHERE id = ?',
      [userId]
    );

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

    const user = users[0];

    // Create deposit record
    const [result] = await pool.execute(
      `INSERT INTO deposits (
        user_id,
        payment_method_id,
        reference,
        amount,
        fee,
        amount_credited,
        status,
        currency,
        expires_at,
        created_at,
        updated_at
      ) VALUES (?, ?, ?, ?, ?, ?, 'pending', 'NGN', DATE_ADD(NOW(), INTERVAL 30 MINUTE), NOW(), NOW())`,
      [userId, payment_method_id, reference, amount, totalFee, amountCredited]
    );

    const depositId = result.insertId;

    // Initialize payment with service
    const factory = getPaymentServiceFactory(pool);
    const service = factory.getService(method.code);

    const metadata = {
      user_id: userId,
      customer_name: `${user.first_name || ''} ${user.last_name || ''}`.trim() || 'WakaTraffic User',
      customer_email: user.email,
      phone: user.mobile_number,
      deposit_id: depositId
    };

    const paymentResult = await service.initializePayment(amount, reference, metadata);

    if (paymentResult.success) {
      // Update deposit with payment details
      if (paymentResult.data.account_number) {
        // Virtual account payment
        await pool.execute(
          `UPDATE deposits SET
            payment_account = ?,
            payment_details = ?,
            status = 'awaiting_payment'
          WHERE id = ?`,
          [
            paymentResult.data.account_number,
            JSON.stringify(paymentResult.data),
            depositId
          ]
        );
      } else if (paymentResult.data.payment_url) {
        // Redirect payment
        await pool.execute(
          `UPDATE deposits SET
            payment_details = ?,
            status = 'awaiting_payment'
          WHERE id = ?`,
          [
            JSON.stringify(paymentResult.data),
            depositId
          ]
        );
      }

      res.json({
        success: true,
        data: {
          deposit_id: depositId,
          reference: reference,
          amount: amount,
          fee: totalFee,
          amount_credited: amountCredited,
          payment_method: method.name,
          payment_details: paymentResult.data,
          expires_at: new Date(Date.now() + 30 * 60 * 1000).toISOString()
        },
        message: paymentResult.message || 'Payment initialized successfully'
      });
    } else {
      // Mark deposit as failed
      await pool.execute(
        `UPDATE deposits SET status = 'failed' WHERE id = ?`,
        [depositId]
      );

      res.status(400).json({
        success: false,
        message: paymentResult.message || 'Failed to initialize payment'
      });
    }
  } catch (error) {
    console.error('Initialize deposit error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to initialize deposit'
    });
  }
});

/**
 * POST /api/deposits/:id/verify
 * Verify deposit payment status
 */
router.post('/:id/verify', authenticateToken, async (req, res) => {
  const pool = req.app.get('pool');
  const userId = req.user.userId;
  const depositId = req.params.id;

  try {
    // Get deposit details
    const [deposits] = await pool.execute(
      `SELECT d.*, pm.code as payment_method_code, pm.name as payment_method_name
       FROM deposits d
       JOIN payment_methods pm ON d.payment_method_id = pm.id
       WHERE d.id = ? AND d.user_id = ?`,
      [depositId, userId]
    );

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

    const deposit = deposits[0];

    // Check if already completed
    if (deposit.status === 'completed') {
      return res.json({
        success: true,
        data: {
          status: 'completed',
          message: 'Payment already completed'
        }
      });
    }

    // Verify with payment service
    const factory = getPaymentServiceFactory(pool);
    const service = factory.getService(deposit.payment_method_code);

    const verificationResult = await service.verifyPayment(deposit.reference);

    if (verificationResult.success && verificationResult.data.status === 'completed') {
      // Begin transaction
      const connection = await pool.getConnection();
      await connection.beginTransaction();

      try {
        // Get current user balance
        const [users] = await connection.execute(
          'SELECT balance FROM users WHERE id = ? FOR UPDATE',
          [userId]
        );

        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, userId]
        );

        // Update deposit status
        await connection.execute(
          `UPDATE deposits SET
            status = 'completed',
            amount_paid = ?,
            transaction_id = ?,
            paid_at = NOW(),
            verified_at = NOW(),
            completed_at = NOW(),
            updated_at = NOW()
          WHERE id = ?`,
          [
            verificationResult.data.amount || deposit.amount,
            verificationResult.data.transaction_id || null,
            depositId
          ]
        );

        // 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())`,
          [
            userId,
            depositId,
            deposit.amount_credited,
            newBalance,
            `Deposit via ${deposit.payment_method_name}`,
            deposit.reference
          ]
        );

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

        res.json({
          success: true,
          data: {
            status: 'completed',
            amount_credited: deposit.amount_credited,
            new_balance: newBalance
          },
          message: 'Payment verified and credited successfully'
        });
      } catch (error) {
        await connection.rollback();
        connection.release();
        throw error;
      }
    } else {
      res.json({
        success: true,
        data: {
          status: deposit.status,
          message: 'Payment not yet completed'
        }
      });
    }
  } catch (error) {
    console.error('Verify deposit error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to verify deposit'
    });
  }
});

/**
 * GET /api/deposits/history
 * Get user deposit history
 */
router.get('/history', authenticateToken, async (req, res) => {
  const pool = req.app.get('pool');
  const userId = req.user.userId;
  const { page = 1, limit = 20, status } = req.query;
  const offset = (page - 1) * limit;

  try {
    let query = `
      SELECT
        d.*,
        pm.name as payment_method_name,
        pm.code as payment_method_code,
        pm.type as payment_method_type
      FROM deposits d
      JOIN payment_methods pm ON d.payment_method_id = pm.id
      WHERE d.user_id = ?
    `;

    const params = [userId];

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

    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 WHERE user_id = ?';
    const countParams = [userId];

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

    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 deposit history error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to retrieve deposit history'
    });
  }
});

/**
 * GET /api/deposits/:id
 * Get deposit details
 */
router.get('/:id', authenticateToken, async (req, res) => {
  const pool = req.app.get('pool');
  const userId = req.user.userId;
  const depositId = req.params.id;

  try {
    const [deposits] = await pool.execute(
      `SELECT
        d.*,
        pm.name as payment_method_name,
        pm.code as payment_method_code,
        pm.type as payment_method_type,
        pm.logo_url as payment_method_logo
      FROM deposits d
      JOIN payment_methods pm ON d.payment_method_id = pm.id
      WHERE d.id = ? AND d.user_id = ?`,
      [depositId, userId]
    );

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

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

/**
 * POST /api/deposits/:id/upload-proof
 * Upload payment proof for manual payment methods
 */
router.post('/:id/upload-proof', authenticateToken, async (req, res) => {
  const pool = req.app.get('pool');
  const userId = req.user.userId;
  const depositId = req.params.id;
  const { proof_url, user_note } = req.body;

  try {
    // Get deposit
    const [deposits] = await pool.execute(
      `SELECT d.*, pm.requires_proof
       FROM deposits d
       JOIN payment_methods pm ON d.payment_method_id = pm.id
       WHERE d.id = ? AND d.user_id = ?`,
      [depositId, userId]
    );

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

    const deposit = deposits[0];

    if (!deposit.requires_proof) {
      return res.status(400).json({
        success: false,
        message: 'This payment method does not require proof upload'
      });
    }

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

    // Update deposit with proof
    await pool.execute(
      `UPDATE deposits SET
        payment_proof_url = ?,
        user_note = ?,
        status = 'awaiting_proof',
        updated_at = NOW()
      WHERE id = ?`,
      [proof_url, user_note, depositId]
    );

    res.json({
      success: true,
      message: 'Payment proof uploaded successfully. Awaiting admin verification.'
    });
  } catch (error) {
    console.error('Upload proof error:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to upload payment proof'
    });
  }
});

module.exports = router;
