import { paymentStore } from './store';
import { serverListingsStore } from '../listingsStore';
import { BkashService } from './bkash';
import { NagadService } from './nagad';
import { RocketService } from './rocket';
import { SSLCommerzService } from './sslcommerz';
import { ShurjoPayService } from './shurjopay';
import { AamarPayService } from './aamarpay';
import { UddoktaPayService } from './uddoktapay';
import { PaymentInitParams, PaymentInitResult, ServerTransaction } from './types';

export class PaymentService {
  /**
   * Initialize a new Payment Transaction
   */
  public static async initPayment(
    params: PaymentInitParams,
    appBaseUrl: string
  ): Promise<PaymentInitResult> {
    const { gateway, channel, amount, name, url, facebook_url, website_url, imageUrl, categoryId, categoryName, customerIp } = params;

    // Check gateway status
    const config = paymentStore.getGatewayConfig(gateway);
    if (!config || !config.is_enabled) {
      return {
        success: false,
        transactionId: '',
        gateway,
        mode: 'test',
        action: 'modal',
        message: `Payment gateway "${gateway.toUpperCase()}" is currently disabled or unavailable.`,
      };
    }

    // Fully enforce admin-configured individual payment-method ON/OFF settings
    if (config.allowed_channels !== undefined) {
      if (config.allowed_channels.length === 0) {
        return {
          success: false,
          transactionId: '',
          gateway,
          mode: config.mode,
          action: 'modal',
          message: `All payment methods/channels for "${config.name}" are currently turned OFF in admin settings.`,
        };
      }
      if (channel && !config.allowed_channels.includes(channel)) {
        return {
          success: false,
          transactionId: '',
          gateway,
          mode: config.mode,
          action: 'modal',
          message: `Payment method "${channel}" is currently turned OFF for ${config.name}.`,
        };
      }
    }

    // Generate unique internal transaction ID
    const txnId = `TXN-${gateway.toUpperCase()}-${Date.now().toString().slice(-6)}${Math.floor(1000 + Math.random() * 9000)}`;
    const newListingId = `list_${Date.now()}_${Math.floor(1000 + Math.random() * 9000)}`;
    const nowISO = new Date().toISOString();

    const normalize = (u?: string) => {
      if (!u || typeof u !== 'string') return '';
      let t = u.trim();
      if (!t) return '';
      if (!/^https?:\/\//i.test(t)) t = 'https://' + t;
      return t;
    };

    const finalFbUrl = normalize(facebook_url || url) || 'https://facebook.com';
    const finalWebUrl = normalize(website_url);

    const txn: ServerTransaction = {
      id: `pay_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,
      transaction_id: txnId,
      listing_id: newListingId,
      listing_name: name.trim(),
      listing_url: url || finalFbUrl,
      facebook_url: finalFbUrl,
      website_url: finalWebUrl,
      listing_image: imageUrl || 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=200&auto=format&fit=crop&q=80',
      category_id: categoryId,
      category_name: categoryName,
      amount: Number(amount),
      currency: 'BDT',
      gateway,
      mode: config.mode,
      status: 'pending',
      ip_address: customerIp || '127.0.0.1',
      created_at: nowISO,
      updated_at: nowISO,
    };

    // Store pending transaction record (idempotency start)
    paymentStore.createTransaction(txn);

    const callbackUrl = `${appBaseUrl}/api/payments/${gateway}/callback`;

    // Dispatch to selected gateway handler
    try {
      if (gateway === 'bkash') {
        const res = await BkashService.createPayment(config, txn, callbackUrl);
        if (!res.success || !res.bkashURL) {
          paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: res.message });
          return {
            success: false,
            transactionId: txnId,
            gateway,
            mode: config.mode,
            action: 'modal',
            message: res.message || 'bKash payment initialization failed.',
          };
        }

        return {
          success: true,
          transactionId: txnId,
          gateway,
          mode: config.mode,
          checkoutUrl: res.bkashURL,
          action: 'redirect',
        };
      }

      if (gateway === 'nagad') {
        const res = await NagadService.initPayment(config, txn, callbackUrl);
        if (!res.success || !res.paymentUrl) {
          paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: res.message });
          return {
            success: false,
            transactionId: txnId,
            gateway,
            mode: config.mode,
            action: 'modal',
            message: res.message || 'Nagad initialization failed.',
          };
        }

        return {
          success: true,
          transactionId: txnId,
          gateway,
          mode: config.mode,
          checkoutUrl: res.paymentUrl,
          action: 'redirect',
        };
      }

      if (gateway === 'rocket') {
        const res = await RocketService.initPayment(config, txn, callbackUrl);
        if (!res.success || !res.paymentUrl) {
          paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: res.message });
          return {
            success: false,
            transactionId: txnId,
            gateway,
            mode: config.mode,
            action: 'modal',
            message: res.message || 'DBBL Rocket initialization failed.',
          };
        }

        return {
          success: true,
          transactionId: txnId,
          gateway,
          mode: config.mode,
          checkoutUrl: res.paymentUrl,
          action: 'redirect',
        };
      }

      if (gateway === 'sslcommerz') {
        const res = await SSLCommerzService.initPayment(config, txn, appBaseUrl, channel);
        if (!res.success || !res.gatewayUrl) {
          paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: res.message });
          return {
            success: false,
            transactionId: txnId,
            gateway,
            mode: config.mode,
            action: 'modal',
            message: res.message || 'SSLCommerz session initialization failed.',
          };
        }

        return {
          success: true,
          transactionId: txnId,
          gateway,
          mode: config.mode,
          checkoutUrl: res.gatewayUrl,
          action: 'redirect',
        };
      }

      if (gateway === 'shurjopay') {
        const res = await ShurjoPayService.initPayment(config, txn, appBaseUrl);
        return {
          success: true,
          transactionId: txnId,
          gateway,
          mode: config.mode,
          checkoutUrl: res.checkoutUrl,
          action: 'redirect',
        };
      }

      if (gateway === 'aamarpay') {
        const res = await AamarPayService.initPayment(config, txn, appBaseUrl, channel);
        if (!res.success || !res.gatewayUrl) {
          paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: res.message });
          return {
            success: false,
            transactionId: txnId,
            gateway,
            mode: config.mode,
            action: 'modal',
            message: res.message || 'aamarPay session initialization failed.',
          };
        }

        return {
          success: true,
          transactionId: txnId,
          gateway,
          mode: config.mode,
          checkoutUrl: res.gatewayUrl,
          action: 'redirect',
        };
      }

      if (gateway === 'uddoktapay') {
        const res = await UddoktaPayService.initPayment(config, txn, appBaseUrl, channel);
        if (!res.success || !res.gatewayUrl) {
          paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: res.message });
          return {
            success: false,
            transactionId: txnId,
            gateway,
            mode: config.mode,
            action: 'modal',
            message: res.message || 'UddoktaPay session initialization failed.',
          };
        }

        return {
          success: true,
          transactionId: txnId,
          gateway,
          mode: config.mode,
          checkoutUrl: res.gatewayUrl,
          action: 'redirect',
        };
      }

      return {
        success: false,
        transactionId: txnId,
        gateway,
        mode: config.mode,
        action: 'modal',
        message: `Unsupported gateway ${gateway}`,
      };
    } catch (err: any) {
      paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: err.message });
      return {
        success: false,
        transactionId: txnId,
        gateway,
        mode: config.mode,
        action: 'modal',
        message: err.message || 'Unexpected server error during payment initiation.',
      };
    }
  }

  /**
   * Handle bKash Callback & Server Verification
   */
  public static async handleBkashCallback(
    queryParams: Record<string, any>
  ): Promise<{ success: boolean; transactionId: string; message: string; transaction?: ServerTransaction }> {
    const { paymentID, status, merchantInvoiceNumber } = queryParams;
    const txnId = merchantInvoiceNumber || Object.keys(queryParams).find(k => k.startsWith('TXN-'));

    if (!txnId) {
      return { success: false, transactionId: '', message: 'Missing transaction reference in bKash callback.' };
    }

    const txn = paymentStore.getTransaction(txnId);
    if (!txn) {
      return { success: false, transactionId: txnId, message: 'Transaction record not found.' };
    }

    if (txn.status === 'paid') {
      return { success: true, transactionId: txnId, message: 'Payment already verified.', transaction: txn };
    }

    if (status === 'cancel') {
      paymentStore.updateTransactionStatus(txnId, 'cancelled', { failure_reason: 'User cancelled payment at bKash.' });
      return { success: false, transactionId: txnId, message: 'Payment was cancelled.' };
    }

    if (status === 'failure') {
      paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: 'bKash returned failure status.' });
      return { success: false, transactionId: txnId, message: 'Payment failed at bKash.' };
    }

    // Execute payment with bKash API
    const config = paymentStore.getGatewayConfig('bkash') || { id: 'bkash', name: 'bKash', is_enabled: true, mode: 'test' };
    const execRes = await BkashService.executePayment(config, paymentID || txn.transaction_id);

    if (execRes.success) {
      const updateResult = paymentStore.updateTransactionStatus(txnId, 'paid', {
        gateway_transaction_id: execRes.trxID || `TRX_${Date.now()}`,
        gateway_response: execRes.data,
        paid_at: new Date().toISOString(),
      });

      if (updateResult.transaction) {
        serverListingsStore.processVerifiedBid(updateResult.transaction);
      }

      return {
        success: true,
        transactionId: txnId,
        message: 'Payment verified and confirmed by bKash.',
        transaction: updateResult.transaction,
      };
    }

    paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: execRes.message });
    return {
      success: false,
      transactionId: txnId,
      message: execRes.message || 'bKash verification failed.',
    };
  }

  /**
   * Handle SSLCommerz Callback & Server-to-Server Validation
   */
  public static async handleSSLCommerzCallback(
    bodyOrQuery: Record<string, any>
  ): Promise<{ success: boolean; transactionId: string; message: string; transaction?: ServerTransaction }> {
    const { tran_id, val_id, status, error } = bodyOrQuery;
    const txnId = tran_id;

    if (!txnId) {
      return { success: false, transactionId: '', message: 'Missing tran_id in SSLCommerz payload.' };
    }

    const txn = paymentStore.getTransaction(txnId);
    if (!txn) {
      return { success: false, transactionId: txnId, message: 'Transaction record not found.' };
    }

    // Idempotency: if already paid, return existing success state
    if (txn.status === 'paid') {
      return { success: true, transactionId: txnId, message: 'Transaction already paid.', transaction: txn };
    }

    if (status === 'CANCELLED') {
      paymentStore.updateTransactionStatus(txnId, 'cancelled', { failure_reason: 'User cancelled payment at SSLCommerz.' });
      return { success: false, transactionId: txnId, message: 'Payment was cancelled.' };
    }

    if (status === 'FAILED') {
      paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: error || 'SSLCommerz payment failed.' });
      return { success: false, transactionId: txnId, message: 'Payment failed at SSLCommerz.' };
    }

    // Validate server-to-server with SSLCommerz API
    const config = paymentStore.getGatewayConfig('sslcommerz') || { id: 'sslcommerz', name: 'SSLCommerz', is_enabled: true, mode: 'test' };
    const valRes = await SSLCommerzService.validateTransaction(config, val_id || 'SSL_DEMO_01', txn.amount, txn.transaction_id);

    if (valRes.valid) {
      const update = paymentStore.updateTransactionStatus(txnId, 'paid', {
        gateway_transaction_id: val_id || `VAL_${Date.now()}`,
        gateway_response: valRes.data,
        paid_at: new Date().toISOString(),
      });

      if (update.transaction) {
        serverListingsStore.processVerifiedBid(update.transaction);
      }

      return {
        success: true,
        transactionId: txnId,
        message: 'SSLCommerz payment validated successfully.',
        transaction: update.transaction,
      };
    }

    paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: valRes.message || 'Validation failed' });
    return {
      success: false,
      transactionId: txnId,
      message: valRes.message || 'SSLCommerz validation failed.',
    };
  }

  /**
   * Handle Nagad Callback & Verification
   */
  public static async handleNagadCallback(
    queryParams: Record<string, any>
  ): Promise<{ success: boolean; transactionId: string; message: string; transaction?: ServerTransaction }> {
    const { payment_ref_id, order_id, status } = queryParams;
    const txnId = order_id;

    if (!txnId) {
      return { success: false, transactionId: '', message: 'Missing order_id in Nagad callback.' };
    }

    const txn = paymentStore.getTransaction(txnId);
    if (!txn) {
      return { success: false, transactionId: txnId, message: 'Transaction not found.' };
    }

    if (txn.status === 'paid') {
      return { success: true, transactionId: txnId, message: 'Already marked as paid.', transaction: txn };
    }

    const config = paymentStore.getGatewayConfig('nagad') || { id: 'nagad', name: 'Nagad', is_enabled: true, mode: 'test' };
    const verifyRes = await NagadService.verifyPayment(config, payment_ref_id || 'NAGAD_REF');

    if (verifyRes.verified) {
      const update = paymentStore.updateTransactionStatus(txnId, 'paid', {
        gateway_transaction_id: payment_ref_id || `NAGAD_${Date.now()}`,
        gateway_response: verifyRes.data,
        paid_at: new Date().toISOString(),
      });

      if (update.transaction) {
        serverListingsStore.processVerifiedBid(update.transaction);
      }

      return {
        success: true,
        transactionId: txnId,
        message: 'Nagad payment successfully verified.',
        transaction: update.transaction,
      };
    }

    paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: verifyRes.message });
    return {
      success: false,
      transactionId: txnId,
      message: verifyRes.message || 'Nagad verification failed.',
    };
  }

  /**
   * Handle DBBL Rocket Callback & Verification
   */
  public static async handleRocketCallback(
    queryParams: Record<string, any>
  ): Promise<{ success: boolean; transactionId: string; message: string; transaction?: ServerTransaction }> {
    const { order_id } = queryParams;
    const txnId = order_id;

    if (!txnId) {
      return { success: false, transactionId: '', message: 'Missing order_id in Rocket callback.' };
    }

    const txn = paymentStore.getTransaction(txnId);
    if (!txn) {
      return { success: false, transactionId: txnId, message: 'Transaction not found.' };
    }

    if (txn.status === 'paid') {
      return { success: true, transactionId: txnId, message: 'Already paid.', transaction: txn };
    }

    const config = paymentStore.getGatewayConfig('rocket') || { id: 'rocket', name: 'Rocket', is_enabled: true, mode: 'test' };
    const verifyRes = await RocketService.verifyPayment(config, order_id);

    if (verifyRes.verified) {
      const update = paymentStore.updateTransactionStatus(txnId, 'paid', {
        gateway_transaction_id: `ROCKET_TRX_${Date.now()}`,
        gateway_response: verifyRes.data,
        paid_at: new Date().toISOString(),
      });

      if (update.transaction) {
        serverListingsStore.processVerifiedBid(update.transaction);
      }

      return {
        success: true,
        transactionId: txnId,
        message: 'Rocket transaction confirmed.',
        transaction: update.transaction,
      };
    }

    paymentStore.updateTransactionStatus(txnId, 'failed', { failure_reason: verifyRes.message });
    return {
      success: false,
      transactionId: txnId,
      message: verifyRes.message || 'Rocket verification failed.',
    };
  }

  /**
   * Handle aamarPay Callback & Server-to-Server Verification
   */
  public static async handleAamarPayCallback(
    bodyOrQuery: Record<string, any>
  ): Promise<{ success: boolean; transactionId: string; message: string; transaction?: ServerTransaction }> {
    const { mer_txnid, tran_id, pg_txnid, pay_status, status, error_title, error_desc, reason } = bodyOrQuery;
    const txnId = mer_txnid || tran_id || Object.keys(bodyOrQuery).find(k => k.startsWith('TXN-'));

    if (!txnId) {
      return { success: false, transactionId: '', message: 'Missing transaction identifier in aamarPay callback.' };
    }

    const txn = paymentStore.getTransaction(txnId);
    if (!txn) {
      return { success: false, transactionId: txnId, message: 'Transaction record not found.' };
    }

    // Idempotency: If already paid, return confirmed transaction
    if (txn.status === 'paid') {
      return { success: true, transactionId: txnId, message: 'Transaction already verified and paid.', transaction: txn };
    }

    const normalizedStatus = (pay_status || status || '').toString().toLowerCase();

    if (normalizedStatus.includes('cancel')) {
      paymentStore.updateTransactionStatus(txnId, 'cancelled', {
        failure_reason: 'User cancelled payment at aamarPay checkout.',
      });
      return { success: false, transactionId: txnId, message: 'Payment was cancelled.' };
    }

    if (normalizedStatus.includes('fail') || normalizedStatus.includes('reject')) {
      paymentStore.updateTransactionStatus(txnId, 'failed', {
        failure_reason: error_title || error_desc || reason || 'aamarPay payment failed.',
      });
      return { success: false, transactionId: txnId, message: 'Payment failed at aamarPay.' };
    }

    // Server-to-Server Verification
    const config = paymentStore.getGatewayConfig('aamarpay') || {
      id: 'aamarpay',
      name: 'aamarPay',
      is_enabled: true,
      mode: 'test',
    };

    const verifyTargetId = pg_txnid || txnId;
    const verifyRes = await AamarPayService.verifyTransaction(config, verifyTargetId, txn.amount, txn.transaction_id);

    if (verifyRes.valid) {
      const update = paymentStore.updateTransactionStatus(txnId, 'paid', {
        gateway_transaction_id: pg_txnid || verifyRes.data?.pg_txnid || `AAMAR_${Date.now()}`,
        gateway_response: { ...bodyOrQuery, verification: verifyRes.data },
        paid_at: new Date().toISOString(),
      });

      if (update.transaction) {
        serverListingsStore.processVerifiedBid(update.transaction);
      }

      return {
        success: true,
        transactionId: txnId,
        message: 'aamarPay payment successfully verified.',
        transaction: update.transaction,
      };
    }

    paymentStore.updateTransactionStatus(txnId, 'failed', {
      failure_reason: verifyRes.message || 'aamarPay server verification failed.',
    });

    return {
      success: false,
      transactionId: txnId,
      message: verifyRes.message || 'aamarPay server verification failed.',
    };
  }

  /**
   * Handle UddoktaPay Callback & Server Verification
   */
  public static async handleUddoktaPayCallback(
    bodyOrQuery: Record<string, any>
  ): Promise<{ success: boolean; transactionId: string; message: string; transaction?: ServerTransaction }> {
    const invoice_id = bodyOrQuery.invoice_id || bodyOrQuery.invoiceId;
    const status = (bodyOrQuery.status || '').toString().toLowerCase();
    const txnIdQuery = bodyOrQuery.txn || bodyOrQuery.transaction_id;

    if (status === 'cancel' || status === 'cancelled') {
      if (txnIdQuery) {
        paymentStore.updateTransactionStatus(txnIdQuery, 'cancelled', {
          failure_reason: 'User cancelled payment at UddoktaPay checkout.',
        });
      }
      return { success: false, transactionId: txnIdQuery || '', message: 'Payment was cancelled at UddoktaPay.' };
    }

    if (!invoice_id) {
      return { success: false, transactionId: txnIdQuery || '', message: 'Missing invoice_id in UddoktaPay callback.' };
    }

    // Lookup transaction either from txn query parameter or by finding matching transaction
    let txn = txnIdQuery ? paymentStore.getTransaction(txnIdQuery) : undefined;

    // Server-to-Server Verification with UddoktaPay API
    const config = paymentStore.getGatewayConfig('uddoktapay') || {
      id: 'uddoktapay',
      name: 'UddoktaPay',
      is_enabled: true,
      mode: 'test',
    };

    const verifyRes = await UddoktaPayService.verifyPayment(
      config,
      invoice_id,
      txn?.amount,
      txn?.transaction_id
    );

    if (!verifyRes.valid) {
      if (txn) {
        paymentStore.updateTransactionStatus(txn.transaction_id, 'failed', {
          failure_reason: verifyRes.message || 'UddoktaPay server verification failed.',
        });
      }
      return {
        success: false,
        transactionId: txn?.transaction_id || '',
        message: verifyRes.message || 'UddoktaPay payment verification failed.',
      };
    }

    // If txn wasn't found by query param, resolve from verify data metadata
    if (!txn) {
      const metaTxnId = verifyRes.data?.metadata?.transaction_id || verifyRes.data?.metadata?.order_id;
      if (metaTxnId) {
        txn = paymentStore.getTransaction(metaTxnId);
      }
    }

    if (!txn) {
      const allTxns = paymentStore.getAllTransactions();
      txn = allTxns.find(t => t.gateway === 'uddoktapay' && t.status === 'pending');
    }

    if (!txn) {
      return { success: false, transactionId: '', message: 'Associated transaction record not found.' };
    }

    // Idempotency check: if already paid, return existing confirmed transaction
    if (txn.status === 'paid') {
      return { success: true, transactionId: txn.transaction_id, message: 'Transaction already verified and paid.', transaction: txn };
    }

    // Re-check exact amount
    const verifiedAmount = parseFloat(verifyRes.data?.amount || verifyRes.data?.charged_amount || '0');
    if (txn.amount > 0 && Math.abs(verifiedAmount - txn.amount) > 0.01) {
      paymentStore.updateTransactionStatus(txn.transaction_id, 'failed', {
        failure_reason: `Amount mismatch: expected ৳${txn.amount}, received ৳${verifiedAmount}`,
      });
      return {
        success: false,
        transactionId: txn.transaction_id,
        message: `Amount mismatch: expected ৳${txn.amount}, received ৳${verifiedAmount}`,
      };
    }

    const update = paymentStore.updateTransactionStatus(txn.transaction_id, 'paid', {
      gateway_transaction_id: verifyRes.data?.transaction_id || invoice_id,
      gateway_response: { ...bodyOrQuery, verification: verifyRes.data },
      paid_at: new Date().toISOString(),
    });

    if (update.transaction) {
      serverListingsStore.processVerifiedBid(update.transaction);
    }

    return {
      success: true,
      transactionId: txn.transaction_id,
      message: 'UddoktaPay payment successfully verified.',
      transaction: update.transaction,
    };
  }

  /**
   * Handle UddoktaPay Webhook / IPN Notification
   */
  public static async handleUddoktaPayIpn(
    payload: Record<string, any>,
    headers?: Record<string, any>
  ): Promise<{ success: boolean; message: string; transaction?: ServerTransaction }> {
    const invoice_id = payload.invoice_id || payload.invoiceId;
    const apiKeyHeader = headers?.['rt-uddoktapay-api-key'] || headers?.['RT-UDDOKTAPAY-API-KEY'];

    const config = paymentStore.getGatewayConfig('uddoktapay') || {
      id: 'uddoktapay',
      name: 'UddoktaPay',
      is_enabled: true,
      mode: 'test',
    };

    // Security check on IPN webhook if API key header sent
    const configuredKey = UddoktaPayService.getApiKey(config);
    if (apiKeyHeader && configuredKey && apiKeyHeader !== configuredKey) {
      return { success: false, message: 'Unauthorized IPN request: API Key mismatch.' };
    }

    if (!invoice_id) {
      return { success: false, message: 'Missing invoice_id in IPN payload.' };
    }

    const metaTxnId = payload.metadata?.transaction_id || payload.metadata?.order_id;
    let txn = metaTxnId ? paymentStore.getTransaction(metaTxnId) : undefined;

    // Server-to-server verification
    const verifyRes = await UddoktaPayService.verifyPayment(
      config,
      invoice_id,
      txn?.amount,
      txn?.transaction_id
    );

    if (!verifyRes.valid) {
      return { success: false, message: verifyRes.message || 'IPN verification failed.' };
    }

    if (!txn) {
      const verifiedMetaTxnId = verifyRes.data?.metadata?.transaction_id;
      if (verifiedMetaTxnId) {
        txn = paymentStore.getTransaction(verifiedMetaTxnId);
      }
    }

    if (!txn) {
      return { success: false, message: 'Transaction not found for verified IPN.' };
    }

    // Idempotency: avoid double processing
    if (txn.status === 'paid') {
      return { success: true, message: 'Transaction already paid and processed.', transaction: txn };
    }

    const update = paymentStore.updateTransactionStatus(txn.transaction_id, 'paid', {
      gateway_transaction_id: verifyRes.data?.transaction_id || invoice_id,
      gateway_response: { ipn_payload: payload, verification: verifyRes.data },
      paid_at: new Date().toISOString(),
    });

    if (update.transaction) {
      serverListingsStore.processVerifiedBid(update.transaction);
    }

    return {
      success: true,
      message: 'UddoktaPay IPN processed successfully.',
      transaction: update.transaction,
    };
  }

  /**
   * Handle Test Sandbox Simulator Actions
   */
  public static async simulateSandboxCompletion(
    transactionId: string,
    action: 'success' | 'fail' | 'cancel'
  ): Promise<{ success: boolean; message: string; transaction?: ServerTransaction }> {
    const txn = paymentStore.getTransaction(transactionId);
    if (!txn) {
      return { success: false, message: 'Transaction not found.' };
    }

    if (action === 'success') {
      const update = paymentStore.updateTransactionStatus(transactionId, 'paid', {
        gateway_transaction_id: `SIM_${txn.gateway.toUpperCase()}_${Date.now()}`,
        gateway_response: {
          simulated: true,
          mode: 'test_sandbox',
          timestamp: new Date().toISOString(),
        },
        paid_at: new Date().toISOString(),
      });

      if (update.transaction) {
        serverListingsStore.processVerifiedBid(update.transaction);
      }

      return {
        success: true,
        message: `Sandbox payment completed and verified via ${txn.gateway.toUpperCase()}.`,
        transaction: update.transaction,
      };
    }

    if (action === 'cancel') {
      paymentStore.updateTransactionStatus(transactionId, 'cancelled', {
        failure_reason: 'User cancelled payment in sandbox simulator.',
      });
      return { success: false, message: 'Sandbox payment cancelled.' };
    }

    paymentStore.updateTransactionStatus(transactionId, 'failed', {
      failure_reason: 'Simulated payment failure (e.g. insufficient funds or bad OTP).',
    });
    return { success: false, message: 'Sandbox payment failed.' };
  }
}
