/**
 * OpayService
 * Handles Opay mobile money payments
 * Features: Payment URL generation, callback verification
 */

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

class OpayService extends PaymentServiceInterface {
  constructor() {
    super();
    this.apiUrl = process.env.OPAY_API_URL || 'https://api.opayweb.com/v3';
    this.merchantId = process.env.OPAY_MERCHANT_ID;
    this.publicKey = process.env.OPAY_PUBLIC_KEY;
    this.privateKey = process.env.OPAY_PRIVATE_KEY;
  }

  /**
   * Generate signature for Opay API requests
   */
  generateSignature(data) {
    // Sort keys alphabetically
    const sortedKeys = Object.keys(data).sort();
    let signStr = '';

    for (const key of sortedKeys) {
      const value = data[key];
      if (value !== '' && value !== null && value !== undefined && key !== 'signature') {
        signStr += `${key}=${value}&`;
      }
    }

    signStr += `privateKey=${this.privateKey}`;

    return crypto.createHash('sha512').update(signStr).digest('hex');
  }

  /**
   * Initialize payment
   */
  async initializePayment(amount, reference, metadata = {}) {
    try {
      const callbackUrl = metadata.callbackUrl || `${process.env.APP_URL}/api/webhooks/opay`;
      const returnUrl = metadata.returnUrl || `${process.env.APP_URL}/deposits/success`;

      const data = {
        reference: reference,
        mchShortName: this.merchantId,
        productName: 'WakaTraffic Deposit',
        productDesc: 'Add funds to WakaTraffic account',
        userPhone: metadata.phone || '',
        userRequestIp: metadata.ip || '',
        amount: {
          total: Math.round(amount * 100), // Convert to kobo
          currency: 'NGN'
        },
        callbackUrl: callbackUrl,
        returnUrl: returnUrl,
        expireAt: Math.floor(Date.now() / 1000) + (30 * 60) // 30 minutes
      };

      data.signature = this.generateSignature(data);

      const response = await axios.post(`${this.apiUrl}/cashier/initialize`, data, {
        headers: { 'Content-Type': 'application/json' }
      });

      if (response.data && response.data.code === '00000') {
        return {
          success: true,
          data: {
            payment_url: response.data.data.cashierUrl,
            reference: reference,
            expires_at: new Date(data.expireAt * 1000).toISOString()
          },
          message: 'Payment initialized successfully'
        };
      }

      return {
        success: false,
        message: response.data?.message || 'Failed to initialize payment'
      };
    } catch (error) {
      console.error('Opay init error:', error.message);
      return {
        success: false,
        message: `Initialization failed: ${error.message}`
      };
    }
  }

  /**
   * Verify payment
   */
  async verifyPayment(reference) {
    try {
      const data = {
        reference: reference,
        mchShortName: this.merchantId
      };

      data.signature = this.generateSignature(data);

      const response = await axios.post(`${this.apiUrl}/cashier/status`, data, {
        headers: { 'Content-Type': 'application/json' }
      });

      if (response.data && response.data.code === '00000') {
        const result = response.data.data;

        if (result.status === 'SUCCESS') {
          return {
            success: true,
            data: {
              status: 'completed',
              amount: result.amount.total / 100,
              reference: reference,
              transaction_id: result.orderNo,
              payment_time: result.payTime
            },
            message: 'Payment completed successfully'
          };
        } else {
          return {
            success: false,
            data: {
              status: result.status.toLowerCase(),
              reference: reference
            },
            message: `Payment status: ${result.status}`
          };
        }
      }

      return {
        success: false,
        message: 'Failed to verify payment'
      };
    } catch (error) {
      console.error('Opay verify error:', error.message);
      return {
        success: false,
        message: `Verification 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 from Opay
   */
  async handleWebhook(payload, headers = {}) {
    try {
      if (payload.status === 'SUCCESS') {
        return {
          success: true,
          data: {
            reference: payload.reference,
            amount: payload.amount.total / 100,
            status: 'completed',
            transaction_id: payload.orderNo
          }
        };
      }

      return {
        success: false,
        data: {
          status: payload.status?.toLowerCase() || 'failed',
          reference: payload.reference
        }
      };
    } catch (error) {
      console.error('Opay webhook error:', error.message);
      return { success: false, message: error.message };
    }
  }

  /**
   * Verify webhook signature
   */
  verifyWebhookSignature(payload, signature) {
    try {
      const data = typeof payload === 'string' ? JSON.parse(payload) : payload;
      const computedSignature = this.generateSignature(data);

      return crypto.timingSafeEqual(
        Buffer.from(computedSignature),
        Buffer.from(signature)
      );
    } catch (error) {
      console.error('Opay signature verification error:', error.message);
      return false;
    }
  }

  /**
   * Get service configuration
   */
  getConfig() {
    return {
      name: 'Opay',
      code: 'opay',
      type: 'mobile_money',
      isAutomated: true,
      requiresProof: false,
      processingTime: 0 // Instant
    };
  }
}

module.exports = OpayService;
