/**
 * PalmPayService
 * Handles PalmPay mobile money payments
 * Features: Payment URL generation, callback verification
 */

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

class PalmPayService extends PaymentServiceInterface {
  constructor() {
    super();
    this.apiUrl = process.env.PALMPAY_API_URL || 'https://api.palmpay.com/payment/v1';
    this.merchantId = process.env.PALMPAY_MERCHANT_ID;
    this.publicKey = process.env.PALMPAY_PUBLIC_KEY;
    this.privateKey = process.env.PALMPAY_PRIVATE_KEY;
  }

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

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

    signStr += `timestamp=${timestamp}`;

    return crypto
      .createHmac('sha256', this.privateKey)
      .update(signStr)
      .digest('hex');
  }

  /**
   * Initialize payment
   */
  async initializePayment(amount, reference, metadata = {}) {
    try {
      const timestamp = String(Math.floor(Date.now() / 1000));
      const notifyUrl = metadata.notifyUrl || `${process.env.APP_URL}/api/webhooks/palmpay`;
      const returnUrl = metadata.returnUrl || `${process.env.APP_URL}/deposits/success`;

      const data = {
        merchantId: this.merchantId,
        merchantOrderNo: reference,
        amount: {
          amount: Math.round(amount * 100), // Convert to kobo
          currency: 'NGN'
        },
        subject: 'WakaTraffic Deposit',
        notifyUrl: notifyUrl,
        returnUrl: returnUrl,
        expireTime: Math.floor(Date.now() / 1000) + (30 * 60) // 30 minutes
      };

      const signature = this.generateSignature(data, timestamp);

      const response = await axios.post(
        `${this.apiUrl}/pay/unified`,
        data,
        {
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${this.publicKey}`,
            'Sign': signature,
            'Timestamp': timestamp
          }
        }
      );

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

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

  /**
   * Verify payment
   */
  async verifyPayment(reference) {
    try {
      const timestamp = String(Math.floor(Date.now() / 1000));

      const data = {
        merchantId: this.merchantId,
        merchantOrderNo: reference
      };

      const signature = this.generateSignature(data, timestamp);

      const response = await axios.post(
        `${this.apiUrl}/pay/query`,
        data,
        {
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${this.publicKey}`,
            'Sign': signature,
            'Timestamp': timestamp
          }
        }
      );

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

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

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

      return {
        success: false,
        data: {
          status: payload.status?.toLowerCase() || 'failed',
          reference: payload.merchantOrderNo
        }
      };
    } catch (error) {
      console.error('PalmPay 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 timestamp = data.timestamp || String(Math.floor(Date.now() / 1000));
      const computedSignature = this.generateSignature(data, timestamp);

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

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

module.exports = PalmPayService;
