/**
 * BankTransferService
 * Handles manual bank transfer payments
 * Features: Bank details display, proof upload, manual verification
 */

const PaymentServiceInterface = require('./PaymentServiceInterface');

class BankTransferService extends PaymentServiceInterface {
  constructor(pool) {
    super();
    this.pool = pool; // Database connection pool
    this.bankAccounts = [
      {
        bank_name: 'Access Bank',
        account_number: '0123456789',
        account_name: 'WakaTraffic Limited',
        bank_code: '044'
      },
      {
        bank_name: 'GTBank',
        account_number: '0987654321',
        account_name: 'WakaTraffic Limited',
        bank_code: '058'
      },
      {
        bank_name: 'First Bank',
        account_number: '1234567890',
        account_name: 'WakaTraffic Limited',
        bank_code: '011'
      }
    ];
  }

  /**
   * Initialize payment - Return bank details
   */
  async initializePayment(amount, reference, metadata = {}) {
    try {
      return {
        success: true,
        data: {
          bank_accounts: this.bankAccounts,
          amount: amount,
          reference: reference,
          instructions: [
            `Transfer exactly ₦${amount.toLocaleString()} to any of our bank accounts above`,
            'Use your unique reference as the transfer description/narration',
            'Upload your payment proof (screenshot or receipt) after transfer',
            'Your account will be credited within 5-10 minutes after verification'
          ],
          expires_at: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() // 24 hours
        },
        message: 'Bank transfer details generated successfully'
      };
    } catch (error) {
      console.error('Bank transfer init error:', error.message);
      return {
        success: false,
        message: `Initialization failed: ${error.message}`
      };
    }
  }

  /**
   * Verify payment - Check if proof has been uploaded and verified
   */
  async verifyPayment(reference) {
    try {
      if (!this.pool) {
        return {
          success: false,
          message: 'Database connection not available'
        };
      }

      const [deposits] = await this.pool.execute(
        `SELECT status, amount, payment_proof_url, verified_at, verified_by
         FROM deposits
         WHERE reference = ?`,
        [reference]
      );

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

      const deposit = deposits[0];

      if (deposit.status === 'completed' && deposit.verified_at) {
        return {
          success: true,
          data: {
            status: 'completed',
            amount: parseFloat(deposit.amount),
            reference: reference,
            verified_at: deposit.verified_at
          },
          message: 'Payment verified and completed'
        };
      } else if (deposit.status === 'verifying' || deposit.payment_proof_url) {
        return {
          success: false,
          data: {
            status: 'verifying',
            reference: reference
          },
          message: 'Payment proof submitted, awaiting admin verification'
        };
      } else {
        return {
          success: false,
          data: {
            status: 'awaiting_proof',
            reference: reference
          },
          message: 'Awaiting payment proof upload'
        };
      }
    } catch (error) {
      console.error('Bank transfer verify error:', error.message);
      return {
        success: false,
        message: `Verification failed: ${error.message}`
      };
    }
  }

  /**
   * Upload payment proof
   */
  async uploadProof(reference, proofUrl, metadata = {}) {
    try {
      if (!this.pool) {
        throw new Error('Database connection not available');
      }

      const [result] = await this.pool.execute(
        `UPDATE deposits
         SET payment_proof_url = ?,
             status = 'verifying',
             payment_account = ?,
             user_note = ?,
             updated_at = NOW()
         WHERE reference = ?`,
        [
          proofUrl,
          metadata.payment_account || null,
          metadata.user_note || null,
          reference
        ]
      );

      if (result.affectedRows > 0) {
        return {
          success: true,
          message: 'Payment proof uploaded successfully. Awaiting admin verification.'
        };
      }

      return {
        success: false,
        message: 'Failed to upload payment proof'
      };
    } catch (error) {
      console.error('Upload proof error:', error.message);
      return {
        success: false,
        message: `Upload failed: ${error.message}`
      };
    }
  }

  /**
   * Admin: Approve manual payment
   * Implements atomic transaction to credit user wallet
   */
  async approvePayment(reference, adminId, adminNote = '') {
    const connection = await this.pool.getConnection();
    await connection.beginTransaction();

    try {
      // Get deposit with user balance (row lock)
      const [deposits] = await connection.execute(
        `SELECT d.*, u.balance as current_balance
         FROM deposits d
         JOIN users u ON d.user_id = u.id
         WHERE d.reference = ? AND d.status = 'verifying'
         FOR UPDATE`,
        [reference]
      );

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

      const deposit = deposits[0];
      const newBalance = parseFloat(deposit.current_balance) + 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 status
      await connection.execute(
        `UPDATE deposits SET status = 'completed', verified_at = NOW(),
          completed_at = NOW(), verified_by = ?, admin_note = ?, updated_at = NOW()
         WHERE reference = ?`,
        [adminId, adminNote, reference]
      );

      // 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', 'Deposit approved by admin', ?, NOW(), NOW())`,
        [deposit.user_id, deposit.id, deposit.amount_credited, newBalance, deposit.reference]
      );

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

      return {
        success: true,
        message: 'Payment approved and user credited',
        data: { amount_credited: deposit.amount_credited, new_balance: newBalance }
      };
    } catch (error) {
      await connection.rollback();
      connection.release();
      console.error('Approve payment error:', error);
      return { success: false, message: `Approval failed: ${error.message}` };
    }
  }

  /**
   * Admin: Reject manual payment
   */
  async rejectPayment(reference, adminId, adminNote = '') {
    try {
      if (!this.pool) {
        throw new Error('Database connection not available');
      }

      const [result] = await this.pool.execute(
        `UPDATE deposits
         SET status = 'failed',
             verified_at = NOW(),
             verified_by = ?,
             admin_note = ?
         WHERE reference = ? AND status = 'verifying'`,
        [adminId, adminNote, reference]
      );

      if (result.affectedRows > 0) {
        return {
          success: true,
          message: 'Payment rejected'
        };
      }

      return {
        success: false,
        message: 'Deposit not found or not in verifying status'
      };
    } catch (error) {
      console.error('Reject payment error:', error.message);
      return {
        success: false,
        message: `Rejection failed: ${error.message}`
      };
    }
  }

  /**
   * Get payment status
   */
  async getPaymentStatus(reference) {
    const verification = await this.verifyPayment(reference);

    if (verification.success) {
      return 'completed';
    } else if (verification.data && verification.data.status) {
      return verification.data.status;
    }

    return 'pending';
  }

  /**
   * Handle webhook - Not applicable for manual transfers
   */
  async handleWebhook(payload, headers = {}) {
    return {
      success: false,
      message: 'Webhooks not supported for manual bank transfers'
    };
  }

  /**
   * Verify webhook signature - Not applicable
   */
  verifyWebhookSignature(payload, signature) {
    return false;
  }

  /**
   * Get service configuration
   */
  getConfig() {
    return {
      name: 'Bank Transfer',
      code: 'bank_transfer',
      type: 'bank_transfer',
      isAutomated: false,
      requiresProof: true,
      processingTime: 10 // 10 minutes average
    };
  }
}

module.exports = BankTransferService;
