<?php

namespace App\Controllers;

use CodeIgniter\RESTful\ResourceController;
use App\Libraries\MobileMoneyService;
use App\Libraries\TransactionManagementService;
use App\Models\PaymentTransactionModel;

class MobileMoney extends ResourceController
{
    protected $mobileMoneyService;
    protected $paymentTransactionModel;
    protected $transactionManagementService;

    public function __construct()
    {
        $this->mobileMoneyService = new MobileMoneyService();
        $this->paymentTransactionModel = new PaymentTransactionModel();
        $this->transactionManagementService = new TransactionManagementService();
    }

    /**
     * Request mobile money payment - Simplified endpoint for in-house apps
     * POST /api/mobile-money/pay
     */
    public function pay()
    {
        // Get JSON input from request
        $json = $this->request->getJSON();

        if (!$json) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON input'
            ], 400);
        }

        // Validate required fields
        if (!isset($json->msisdn) || !isset($json->amount)) {
            return $this->respond([
                'success' => false,
                'message' => 'Missing required fields: msisdn, amount'
            ], 400);
        }

        // Validate phone number
        if (!$this->mobileMoneyService->validatePhoneNumber($json->msisdn)) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid phone number format'
            ], 400);
        }

        // Validate amount
        if (!is_numeric($json->amount) || $json->amount <= 0) {
            return $this->respond([
                'success' => false,
                'message' => 'Amount must be a positive number'
            ], 400);
        }

        // Prepare payment data (currency from formatted MSISDN, not JSON body)
        $msisdn = $this->mobileMoneyService->formatPhoneNumber($json->msisdn);
        $paymentData = [
            'msisdn' => $msisdn,
            'amount' => (float) $json->amount,
            'currency' => $this->mobileMoneyService->currencyFromMsisdn($msisdn),
            'description' => $json->description ?? 'Mobile Money Payment',
            'reference' => $json->reference ?? $this->mobileMoneyService->generateReference()
        ];

        // Make payment request
        $result = $this->mobileMoneyService->requestPayment($paymentData);

        if ($result['success']) {
            // Save comprehensive transaction data to database only on successful API response
            $this->paymentTransactionModel->insert([
                'transaction_id' => $paymentData['reference'],
                'reference' => $result['internal_reference'],
                'msisdn' => $paymentData['msisdn'],
                'amount' => $paymentData['amount'],
                'status' => 'PENDING',
                'currency' => $paymentData['currency'],
                'description' => $paymentData['description'],
                'payment_method' => 'mobile_money',
                'gateway_reference' => $result['internal_reference'],
                'gateway_response' => json_encode($result),
                'client_ip' => $this->request->getIPAddress(),
                'user_agent' => $this->request->getUserAgent(),
                'created_at' => date('Y-m-d H:i:s'),
                'metadata' => json_encode([
                    'api_version' => 'v1',
                    'source' => 'mobile_money_api',
                    'request_data' => $paymentData
                ])
            ]);

            // Post to webhook if configured
            $this->postToWebhook([
                'transaction_id' => $paymentData['reference'],
                'reference' => $result['internal_reference'],
                'msisdn' => $paymentData['msisdn'],
                'amount' => $paymentData['amount'],
                'status' => 'PENDING',
                'created_at' => date('Y-m-d H:i:s')
            ]);
        }

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Get transaction status
     * GET /api/mobile-money/status/{reference}
     */
    public function getStatus($reference = null)
    {
        if (!$reference) {
            return $this->respond([
                'success' => false,
                'message' => 'Reference is required'
            ], 400);
        }

        $transaction = $this->paymentTransactionModel->where('transaction_id', $reference)->first();

        if (!$transaction) {
            return $this->respond([
                'success' => false,
                'message' => 'Transaction not found'
            ], 404);
        }

        return $this->respond([
            'success' => true,
            'transaction' => [
                'reference' => $transaction['transaction_id'],
                'internal_reference' => $transaction['reference'],
                'msisdn' => $transaction['msisdn'],
                'amount' => $transaction['amount'],
                'status' => $transaction['status'],
                'created_at' => $transaction['created_at']
            ]
        ]);
    }

    /**
     * Webhook callback handler for payment status updates
     * POST /api/mobile-money/callback
     */
    public function callback()
    {
        $json = $this->request->getJSON(true);

        if (!$json) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON input'
            ], 400);
        }

        // Log the received callback
        log_message('info', 'Mobile Money Callback received: ' . print_r($json, true));

        // Extract transaction details from callback
        $reference = $json['reference'] ?? $json['transaction_id'] ?? null;
        $status = $json['status'] ?? null;

        if (!$reference || !$status) {
            return $this->respond([
                'success' => false,
                'message' => 'Missing reference or status in callback'
            ], 400);
        }

        // Update transaction status with comprehensive data
        $updateData = [
            'status' => strtoupper($status),
            'updated_at' => date('Y-m-d H:i:s')
        ];

        // Add processed_at timestamp if status is SUCCESS or FAILED
        if (in_array(strtoupper($status), ['SUCCESS', 'FAILED'])) {
            $updateData['processed_at'] = date('Y-m-d H:i:s');
        }

        // Add failure reason if status is FAILED
        if (strtoupper($status) === 'FAILED' && isset($json['reason'])) {
            $updateData['failure_reason'] = $json['reason'];
        }

        // Update webhook attempts
        $updateData['webhook_attempts'] = $this->paymentTransactionModel->where('transaction_id', $reference)->first()['webhook_attempts'] + 1;
        $updateData['last_webhook_attempt'] = date('Y-m-d H:i:s');

        $updateResult = $this->paymentTransactionModel->where('transaction_id', $reference)
            ->set($updateData)
            ->update();

        if ($updateResult) {
            log_message('info', "Transaction {$reference} updated to status: {$status}");
            
            // Post to webhook with updated status
            $transaction = $this->paymentTransactionModel->where('transaction_id', $reference)->first();
            if ($transaction) {
                $this->postToWebhook([
                    'transaction_id' => $transaction['transaction_id'],
                    'reference' => $transaction['reference'],
                    'msisdn' => $transaction['msisdn'],
                    'amount' => $transaction['amount'],
                    'status' => $transaction['status'],
                    'created_at' => $transaction['created_at']
                ]);
            }
        }

        return $this->respond([
            'success' => true,
            'message' => 'Callback processed successfully'
        ]);
    }

    /**
     * Relworx webhook handler - Receives status updates from Relworx API
     * POST /api/mobile-money/webhook/relworx
     * 
     * When the status of a request changes from pending to either failed or success,
     * Relworx sends a POST request including details of the request after processing.
     * We respond with HTTP 200 OK to acknowledge receipt, otherwise sending is retried 10 times.
     */
    public function relworxWebhook()
    {
        // Get raw input for logging
        $rawInput = $this->request->getBody();
        
        // Log the received webhook
        log_message('info', 'Relworx Webhook received: ' . $rawInput);

        // Parse JSON
        $json = $this->request->getJSON(true);

        if (!$json) {
            log_message('error', 'Relworx Webhook: Invalid JSON input');
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON input'
            ], 400);
        }

        // Validate required fields from Relworx webhook
        $requiredFields = ['status', 'internal_reference', 'customer_reference'];
        foreach ($requiredFields as $field) {
            if (!isset($json[$field])) {
                log_message('error', "Relworx Webhook: Missing required field: {$field}");
                return $this->respond([
                    'success' => false,
                    'message' => "Missing required field: {$field}"
                ], 400);
            }
        }

        // Extract data from Relworx webhook
        $statusFromRelworx = strtolower($json['status'] ?? ''); // 'success' or 'failed' (case-insensitive)
        $internalReference = $json['internal_reference'];
        $customerReference = $json['customer_reference'];
        $msisdn = $json['msisdn'] ?? null;
        $amount = $json['amount'] ?? null;
        $currency = $json['currency'] ?? 'UGX';
        $provider = $json['provider'] ?? null;
        $charge = $json['charge'] ?? null;
        $completedAt = $json['completed_at'] ?? null;
        $message = $json['message'] ?? null;

        // Map Relworx status (lowercase) to our status format (uppercase)
        // Relworx sends: "success" or "failed" (lowercase per docs)
        $ourStatus = ($statusFromRelworx === 'success') ? 'SUCCESS' : (($statusFromRelworx === 'failed') ? 'FAILED' : 'PENDING');

        // Resolve webhook to the correct row: product validate + purchase both share customer_reference,
        // so a single OR matched the validation row first and left product_purchase stuck PENDING.
        // 1) Prefer settlement row for product purchases (internal_reference is on purchase row).
        $transaction = $this->paymentTransactionModel
            ->where('payment_method', 'product_purchase')
            ->groupStart()
            ->where('reference', $internalReference)
            ->orWhere('gateway_reference', $internalReference)
            ->groupEnd()
            ->first();

        // 2) Fall back: customer_reference -> transaction_id, or internal_reference -> reference.
        // Exclude product_validation so async settlement never overwrites the validate-only record.
        if (!$transaction) {
            $transaction = $this->paymentTransactionModel
                ->where('payment_method !=', 'product_validation')
                ->groupStart()
                ->where('transaction_id', $customerReference)
                ->orWhere('reference', $internalReference)
                ->groupEnd()
                ->first();
        }

        if (!$transaction) {
            log_message('warning', "Relworx Webhook: Transaction not found - customer_ref: {$customerReference}, internal_ref: {$internalReference}");
            // Still return 200 OK to prevent retries
            return $this->respond([
                'success' => true,
                'message' => 'Transaction not found, but webhook acknowledged'
            ], 200);
        }

        // Prepare update data
        $updateData = [
            'status' => $ourStatus,
            'updated_at' => date('Y-m-d H:i:s'),
            'gateway_reference' => $internalReference,
        ];

        // Add processed_at timestamp
        if (in_array($ourStatus, ['SUCCESS', 'FAILED'])) {
            $updateData['processed_at'] = $completedAt ? date('Y-m-d H:i:s', strtotime($completedAt)) : date('Y-m-d H:i:s');
        }

        // Add failure reason if status is FAILED
        if ($ourStatus === 'FAILED' && $message) {
            $updateData['failure_reason'] = $message;
        }

        // Update metadata with Relworx response (preserve original status from Relworx)
        $existingMetadata = json_decode($transaction['metadata'] ?? '{}', true);
        $existingMetadata['relworx_webhook'] = [
            'received_at' => date('Y-m-d H:i:s'),
            'status' => $json['status'], // Preserve original status from Relworx (lowercase)
            'internal_reference' => $internalReference,
            'provider' => $provider,
            'charge' => $charge,
            'completed_at' => $completedAt,
            'message' => $message
        ];
        $updateData['metadata'] = json_encode($existingMetadata);

        // Update the transaction
        $updateResult = $this->paymentTransactionModel
            ->where('id', $transaction['id'])
            ->set($updateData)
            ->update();

        if ($updateResult) {
            log_message('info', "Relworx Webhook: Transaction {$customerReference} updated to status: {$ourStatus}");
            
            // Forward to configured webhooks
            $webhookData = [
                'transaction_id' => $transaction['transaction_id'],
                'reference' => $internalReference,
                'msisdn' => $msisdn ?? $transaction['msisdn'],
                'amount' => $amount ?? $transaction['amount'],
                'currency' => $currency,
                'status' => $ourStatus,
                'provider' => $provider,
                'charge' => $charge,
                'completed_at' => $completedAt,
                'message' => $message,
                'created_at' => $transaction['created_at'],
                'updated_at' => $updateData['updated_at']
            ];
            
            $this->postToWebhook($webhookData);
        } else {
            log_message('error', "Relworx Webhook: Failed to update transaction {$customerReference}");
        }

        // Forward to Discord webhook
        $this->sendToDiscord($json, $ourStatus, $transaction ?? null);

        // ALWAYS respond with HTTP 200 OK to acknowledge receipt
        // This prevents Relworx from retrying the webhook
        return $this->respond([
            'success' => true,
            'message' => 'Webhook received and processed successfully'
        ], 200);
    }

    /**
     * Post transaction data to configured webhooks
     */
    private function postToWebhook($transaction)
    {
        $db = \Config\Database::connect();
        $query = $db->table('webhooks')->select('url, requires_plus')->get();
        $webhooks = $query->getResultArray();

        if (empty($webhooks)) {
            log_message('info', 'No webhooks configured for mobile money transactions.');
            return;
        }

        $client = \Config\Services::curlrequest();

        foreach ($webhooks as $webhook) {
            $url = trim($webhook['url']);

            if (substr($url, -1) === '/') {
                $url = rtrim($url, '/');
            }

            if (!empty($webhook['requires_plus']) && $webhook['requires_plus'] == 1) {
                $transactionUrl = $url . '/' . $transaction['transaction_id'] . '/+';
            } else {
                $transactionUrl = $url;
            }

            try {
                $response = $client->post($transactionUrl, [
                    "json" => $transaction,
                    "headers" => ["Content-Type" => "application/json"],
                    "timeout" => 60,
                ]);

                log_message('info', 'Mobile Money webhook sent to: ' . $transactionUrl . ' | Response: ' . $response->getBody());
            } catch (\Exception $e) {
                log_message('error', 'Mobile Money webhook failed for ' . $transactionUrl . ' | Error: ' . $e->getMessage());
            }
        }
    }

    /**
     * Send Relworx webhook notification to Discord
     */
    private function sendToDiscord($relworxData, $status, $transaction = null)
    {
        try {
            $discordWebhookUrl = 'https://discord.com/api/webhooks/1358370679807803554/ZZ6gDHRIwmwXnPZcaT8nNS8NXU1G0L7NRfH6Xs50Q3X6txwEzYOqyYXd_fn_l3ny9HU3';
            
            // Determine color based on status
            $color = 0x00FF00; // Green for success
            $statusEmoji = '✅';
            if ($status === 'FAILED') {
                $color = 0xFF0000; // Red for failed
                $statusEmoji = '❌';
            } elseif ($status === 'PENDING') {
                $color = 0xFFFF00; // Yellow for pending
                $statusEmoji = '⏳';
            }

            // Format amount with currency
            $amount = $relworxData['amount'] ?? 0;
            $currency = $relworxData['currency'] ?? 'UGX';
            $formattedAmount = number_format($amount, 2) . ' ' . $currency;

            // Format charge if available
            $charge = isset($relworxData['charge']) ? number_format((float)$relworxData['charge'], 2) . ' ' . $currency : 'N/A';

            // Create Discord embed
            $discordPayload = [
                'embeds' => [
                    [
                        'title' => $statusEmoji . ' Relworx Payment Update',
                        'color' => $color,
                        'fields' => [
                            [
                                'name' => 'Status',
                                'value' => ucfirst($relworxData['status'] ?? 'unknown'),
                                'inline' => true
                            ],
                            [
                                'name' => 'Amount',
                                'value' => $formattedAmount,
                                'inline' => true
                            ],
                            [
                                'name' => 'Charge',
                                'value' => $charge,
                                'inline' => true
                            ],
                            [
                                'name' => 'Customer Reference',
                                'value' => '`' . ($relworxData['customer_reference'] ?? 'N/A') . '`',
                                'inline' => false
                            ],
                            [
                                'name' => 'Internal Reference',
                                'value' => '`' . ($relworxData['internal_reference'] ?? 'N/A') . '`',
                                'inline' => false
                            ],
                            [
                                'name' => 'MSISDN',
                                'value' => $relworxData['msisdn'] ?? 'N/A',
                                'inline' => true
                            ],
                            [
                                'name' => 'Provider',
                                'value' => $relworxData['provider'] ?? 'N/A',
                                'inline' => true
                            ],
                            [
                                'name' => 'Currency',
                                'value' => $currency,
                                'inline' => true
                            ]
                        ],
                        'timestamp' => $relworxData['completed_at'] ?? date('c'),
                        'footer' => [
                            'text' => 'Relworx Webhook'
                        ]
                    ]
                ]
            ];

            // Add message if available
            if (!empty($relworxData['message'])) {
                $discordPayload['embeds'][0]['description'] = $relworxData['message'];
            }

            // Send to Discord
            $client = \Config\Services::curlrequest();
            $response = $client->post($discordWebhookUrl, [
                'json' => $discordPayload,
                'headers' => [
                    'Content-Type' => 'application/json'
                ],
                'timeout' => 10,
                'http_errors' => false
            ]);

            if ($response->getStatusCode() === 200 || $response->getStatusCode() === 204) {
                log_message('info', 'Discord webhook sent successfully');
            } else {
                log_message('warning', 'Discord webhook failed: ' . $response->getStatusCode() . ' - ' . $response->getBody());
            }
        } catch (\Exception $e) {
            // Don't fail the main webhook if Discord fails
            log_message('error', 'Discord webhook error: ' . $e->getMessage());
        }
    }

    /**
     * Health check endpoint
     * GET /api/mobile-money/health
     */
    public function health()
    {
        return $this->respond([
            'success' => true,
            'message' => 'Mobile Money service is running',
            'timestamp' => date('Y-m-d H:i:s')
        ]);
    }

    /**
     * Send payment (disbursement) to mobile money account
     * POST /api/mobile-money/send
     */
    public function send()
    {
        $json = $this->request->getJSON();

        if (!$json) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON data'
            ], 400);
        }

        // Validate required fields
        if (!isset($json->msisdn) || empty($json->msisdn)) {
            return $this->respond([
                'success' => false,
                'message' => 'Phone number (msisdn) is required'
            ], 400);
        }

        // Validate amount
        if (!is_numeric($json->amount) || $json->amount <= 0) {
            return $this->respond([
                'success' => false,
                'message' => 'Amount must be a positive number'
            ], 400);
        }

        // Prepare payment data (currency from formatted MSISDN, not JSON body)
        $msisdn = $this->mobileMoneyService->formatPhoneNumber($json->msisdn);
        $paymentData = [
            'msisdn' => $msisdn,
            'amount' => (float) $json->amount,
            'currency' => $this->mobileMoneyService->currencyFromMsisdn($msisdn),
            'description' => $json->description ?? 'Send Payment',
            'reference' => $json->reference ?? $this->mobileMoneyService->generateReference()
        ];

        // Make send payment request
        $result = $this->mobileMoneyService->sendPayment($paymentData);

        if ($result['success']) {
            // Save comprehensive transaction data to database only on successful API response
            $this->paymentTransactionModel->insert([
                'transaction_id' => $paymentData['reference'],
                'reference' => $result['internal_reference'],
                'msisdn' => $paymentData['msisdn'],
                'amount' => $paymentData['amount'],
                'status' => 'PENDING',
                'currency' => $paymentData['currency'],
                'description' => $paymentData['description'],
                'payment_method' => 'mobile_money_disbursement',
                'gateway_reference' => $result['internal_reference'],
                'gateway_response' => json_encode($result),
                'client_ip' => $this->request->getIPAddress(),
                'user_agent' => $this->request->getUserAgent(),
                'created_at' => date('Y-m-d H:i:s'),
                'metadata' => json_encode([
                    'api_version' => 'v1',
                    'source' => 'mobile_money_send_api',
                    'request_data' => $paymentData,
                    'transaction_type' => 'disbursement'
                ])
            ]);

            // Post to webhook if configured
            $this->postToWebhook([
                'transaction_id' => $paymentData['reference'],
                'reference' => $result['internal_reference'],
                'msisdn' => $paymentData['msisdn'],
                'amount' => $paymentData['amount'],
                'status' => 'PENDING',
                'transaction_type' => 'disbursement',
                'created_at' => date('Y-m-d H:i:s')
            ]);
        }

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Validate mobile number and get customer information
     * POST /api/mobile-money/validate
     */
    public function validateMobile()
    {
        $json = $this->request->getJSON();

        if (!$json) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON data'
            ], 400);
        }

        // Validate required fields
        if (!isset($json->msisdn) || empty($json->msisdn)) {
            return $this->respond([
                'success' => false,
                'message' => 'Phone number (msisdn) is required'
            ], 400);
        }

        // Make validation request
        $result = $this->mobileMoneyService->validateMobileNumber($json->msisdn);

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Check wallet balance
     * GET /api/mobile-money/balance
     * Query: omit currency for UGX+TZS+KES; currency=all same; currency=UGX (or TZS, KES) for one wallet;
     *        comma-separated e.g. UGX,TZS
     */
    public function balance()
    {
        $currencyRaw = $this->request->getGet('currency');

        // No param (Postman default URL) → all supported Relworx wallet currencies
        if ($currencyRaw === null) {
            $result = $this->mobileMoneyService->checkWalletBalances(['UGX', 'TZS', 'KES']);

            return $this->respond($result, $result['success'] ? 200 : 400);
        }

        $currencyParam = is_string($currencyRaw) ? trim($currencyRaw) : '';
        if ($currencyParam === '') {
            $result = $this->mobileMoneyService->checkWalletBalances(['UGX', 'TZS', 'KES']);

            return $this->respond($result, $result['success'] ? 200 : 400);
        }

        $upper = strtoupper($currencyParam);

        if ($upper === 'ALL') {
            $result = $this->mobileMoneyService->checkWalletBalances(['UGX', 'TZS', 'KES']);

            return $this->respond($result, $result['success'] ? 200 : 400);
        }

        if (str_contains($currencyParam, ',')) {
            $parts = array_filter(array_map('trim', explode(',', $currencyParam)));
            $codes = array_map('strtoupper', $parts);
            if (count($codes) > 1) {
                $result = $this->mobileMoneyService->checkWalletBalances($codes);

                return $this->respond($result, $result['success'] ? 200 : 400);
            }
        }

        $currency = $upper !== '' ? $upper : 'UGX';
        $result = $this->mobileMoneyService->checkWalletBalance($currency);

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Check request status using internal reference
     * GET /api/mobile-money/check-status/{internal_reference}
     */
    public function checkRequestStatus($internalReference = null)
    {
        if (!$internalReference) {
            return $this->respond([
                'success' => false,
                'message' => 'Internal reference is required'
            ], 400);
        }

        // Make request status check
        $result = $this->mobileMoneyService->checkRequestStatus($internalReference);

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Get transaction history from Relworx API
     * GET /api/mobile-money/history
     */
    public function history()
    {
        // Make transaction history request
        $result = $this->mobileMoneyService->getTransactionHistory();

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Request payment session for VISA/Mastercard
     * POST /api/mobile-money/payment-session
     */
    public function paymentSession()
    {
        $json = $this->request->getJSON();

        if (!$json) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON data'
            ], 400);
        }

        // Validate required fields
        if (!isset($json->amount) || empty($json->amount)) {
            return $this->respond([
                'success' => false,
                'message' => 'Amount is required'
            ], 400);
        }

        // Validate amount
        if (!is_numeric($json->amount) || $json->amount <= 0) {
            return $this->respond([
                'success' => false,
                'message' => 'Amount must be a positive number'
            ], 400);
        }

        // Prepare payment data
        $paymentData = [
            'amount' => (float) $json->amount,
            'currency' => $json->currency ?? 'UGX',
            'description' => $json->description ?? 'VISA/Mastercard Payment',
            'reference' => $json->reference ?? $this->mobileMoneyService->generateReference()
        ];

        // Make payment session request
        $result = $this->mobileMoneyService->requestPaymentSession($paymentData);

        if ($result['success']) {
            // Save comprehensive transaction data to database only on successful API response
            $this->paymentTransactionModel->insert([
                'transaction_id' => $paymentData['reference'],
                'reference' => $paymentData['reference'],
                'msisdn' => null, // No phone number for card payments
                'amount' => $paymentData['amount'],
                'status' => 'PENDING',
                'currency' => $paymentData['currency'],
                'description' => $paymentData['description'],
                'payment_method' => 'visa_mastercard',
                'gateway_reference' => $paymentData['reference'],
                'gateway_response' => json_encode($result),
                'client_ip' => $this->request->getIPAddress(),
                'user_agent' => $this->request->getUserAgent(),
                'created_at' => date('Y-m-d H:i:s'),
                'metadata' => json_encode([
                    'api_version' => 'v1',
                    'source' => 'visa_payment_session_api',
                    'request_data' => $paymentData,
                    'transaction_type' => 'card_payment',
                    'payment_url' => $result['payment_url'] ?? null
                ])
            ]);

            // Post to webhook if configured
            $this->postToWebhook([
                'transaction_id' => $paymentData['reference'],
                'reference' => $paymentData['reference'],
                'msisdn' => null,
                'amount' => $paymentData['amount'],
                'status' => 'PENDING',
                'transaction_type' => 'card_payment',
                'payment_url' => $result['payment_url'] ?? null,
                'created_at' => date('Y-m-d H:i:s')
            ]);
        }

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Get all available products/services
     * GET /api/mobile-money/services
     */
    public function services()
    {
        $result = $this->mobileMoneyService->getAllProducts();
        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Get categorized services with grouping
     * GET /api/mobile-money/services/categorized
     */
    public function categorizedServices()
    {
        $result = $this->mobileMoneyService->getCategorizedServices();
        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Get price list for a specific service
     * GET /api/mobile-money/services/price-list/{product_code}
     */
    public function servicePriceList($productCode = null)
    {
        if (!$productCode) {
            return $this->respond([
                'success' => false,
                'message' => 'Product code is required'
            ], 400);
        }

        $result = $this->mobileMoneyService->getProductPriceList($productCode);
        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Validate product before purchase
     * POST /api/mobile-money/validate-product
     */
    public function validateProduct()
    {
        $json = $this->request->getJSON();

        if (!$json) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON data'
            ], 400);
        }

        // Validate required fields
        $requiredFields = ['msisdn', 'amount', 'product_code', 'contact_phone'];
        foreach ($requiredFields as $field) {
            if (!isset($json->$field) || empty($json->$field)) {
                return $this->respond([
                    'success' => false,
                    'message' => "Missing required field: {$field}"
                ], 400);
            }
        }

        // Validate amount
        if (!is_numeric($json->amount) || $json->amount <= 0) {
            return $this->respond([
                'success' => false,
                'message' => 'Amount must be a positive number'
            ], 400);
        }

        // Prepare validation data
        $validationData = [
            'msisdn' => $json->msisdn,
            'amount' => (float) $json->amount,
            'currency' => $json->currency ?? 'UGX', // Default to UGX
            'product_code' => $json->product_code,
            'contact_phone' => $json->contact_phone,
            'reference' => $json->reference ?? null,
            'location_id' => $json->location_id ?? null
        ];

        // Make product validation request
        $result = $this->mobileMoneyService->validateProduct($validationData);

        if ($result['success']) {
            // Save validation record to database for tracking
            $this->paymentTransactionModel->insert([
                'transaction_id' => $result['reference'],
                'reference' => $result['reference'],
                'msisdn' => $result['msisdn'],
                'amount' => $result['amount'],
                'status' => 'VALIDATED',
                'currency' => 'UGX',
                'description' => 'Product Validation - ' . $result['product_code'],
                'payment_method' => 'product_validation',
                'gateway_reference' => $result['validation_reference'] ?? null,
                'gateway_response' => json_encode($result),
                'client_ip' => $this->request->getIPAddress(),
                'user_agent' => $this->request->getUserAgent(),
                'created_at' => date('Y-m-d H:i:s'),
                'metadata' => json_encode([
                    'api_version' => 'v1',
                    'source' => 'product_validation_api',
                    'validation_data' => $validationData,
                    'transaction_type' => 'product_validation',
                    'customer_name' => $result['customer_name'] ?? '',
                    'validation_reference' => $result['validation_reference'] ?? null
                ])
            ]);

            // Post to webhook if configured
            $this->postToWebhook([
                'transaction_id' => $result['reference'],
                'reference' => $result['reference'],
                'msisdn' => $result['msisdn'],
                'amount' => $result['amount'],
                'status' => 'VALIDATED',
                'transaction_type' => 'product_validation',
                'product_code' => $result['product_code'],
                'customer_name' => $result['customer_name'] ?? '',
                'validation_reference' => $result['validation_reference'] ?? null,
                'created_at' => date('Y-m-d H:i:s')
            ]);
        }

        return $this->respond($result, $result['success'] ? 200 : 400);
    }
    public function validateBank()
    {
        $json = $this->request->getJSON();

        if (!$json) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON data'
            ], 400);
        }

        // Validate required fields
        $requiredFields = ['msisdn', 'amount', 'product_code', 'contact_phone'];
        foreach ($requiredFields as $field) {
            if (!isset($json->$field) || empty($json->$field)) {
                return $this->respond([
                    'success' => false,
                    'message' => "Missing required field: {$field}"
                ], 400);
            }
        }

        // Validate amount
        if (!is_numeric($json->amount) || $json->amount <= 0) {
            return $this->respond([
                'success' => false,
                'message' => 'Amount must be a positive number'
            ], 400);
        }

        // Prepare validation data
        $validationData = [
            'msisdn' => $json->msisdn,
            'amount' => (float) $json->amount,
            'currency' => $json->currency ?? 'UGX', // Default to UGX
            'product_code' => $json->product_code,
            'contact_phone' => $json->contact_phone,
            'reference' => $json->reference ?? null,
            'location_id' => $json->location_id ?? null
        ];

        // Make product validation request
        $result = $this->mobileMoneyService->validateProduct($validationData);

        if ($result['success']) {
            // Save validation record to database for tracking
            $this->paymentTransactionModel->insert([
                'transaction_id' => $result['reference'],
                'reference' => $result['reference'],
                'msisdn' => $result['msisdn'],
                'amount' => $result['amount'],
                'status' => 'VALIDATED',
                'currency' => 'UGX',
                'description' => 'Product Validation - ' . $result['product_code'],
                'payment_method' => 'product_validation',
                'gateway_reference' => $result['validation_reference'] ?? null,
                'gateway_response' => json_encode($result),
                'client_ip' => $this->request->getIPAddress(),
                'user_agent' => $this->request->getUserAgent(),
                'created_at' => date('Y-m-d H:i:s'),
                'metadata' => json_encode([
                    'api_version' => 'v1',
                    'source' => 'product_validation_api',
                    'validation_data' => $validationData,
                    'transaction_type' => 'product_validation',
                    'customer_name' => $result['customer_name'] ?? '',
                    'validation_reference' => $result['validation_reference'] ?? null
                ])
            ]);

            // Post to webhook if configured
            $this->postToWebhook([
                'transaction_id' => $result['reference'],
                'reference' => $result['reference'],
                'msisdn' => $result['msisdn'],
                'amount' => $result['amount'],
                'status' => 'VALIDATED',
                'transaction_type' => 'product_validation',
                'product_code' => $result['product_code'],
                'customer_name' => $result['customer_name'] ?? '',
                'validation_reference' => $result['validation_reference'] ?? null,
                'created_at' => date('Y-m-d H:i:s')
            ]);
        }

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Purchase product using validation reference
     * POST /api/mobile-money/purchase-product
     */
    public function purchaseProduct()
    {
        $json = $this->request->getJSON();

        if (!$json) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid JSON data'
            ], 400);
        }

        // Validate required fields
        if (!isset($json->validation_reference) || empty($json->validation_reference)) {
            return $this->respond([
                'success' => false,
                'message' => 'Validation reference is required'
            ], 400);
        }

        // Look up validation transaction to get msisdn and amount
        $validationTransaction = $this->paymentTransactionModel
            ->where('gateway_reference', $json->validation_reference)
            ->orWhere('transaction_id LIKE', '%' . $json->validation_reference . '%')
            ->first();

        // Make product purchase request
        $result = $this->mobileMoneyService->purchaseProduct($json->validation_reference);

        if ($result['success']) {
            // Get msisdn and amount from validation transaction if available
            $msisdn = $validationTransaction['msisdn'] ?? '+000000000000'; // Fallback to avoid null
            $amount = $validationTransaction['amount'] ?? 0;
            $description = $validationTransaction['description'] ?? 'Product Purchase';

            // Save purchase record to database for tracking
            $this->paymentTransactionModel->insert([
                'transaction_id' => $result['internal_reference'] ?? $this->mobileMoneyService->generateReference(),
                'reference' => $result['internal_reference'] ?? $this->mobileMoneyService->generateReference(),
                'msisdn' => $msisdn,
                'amount' => $amount,
                'status' => 'PENDING',
                'currency' => 'UGX',
                'description' => $description,
                'payment_method' => 'product_purchase',
                'gateway_reference' => $result['internal_reference'] ?? null,
                'gateway_response' => json_encode($result),
                'client_ip' => $this->request->getIPAddress(),
                'user_agent' => $this->request->getUserAgent(),
                'created_at' => date('Y-m-d H:i:s'),
                'metadata' => json_encode([
                    'api_version' => 'v1',
                    'source' => 'product_purchase_api',
                    'validation_reference' => $json->validation_reference,
                    'transaction_type' => 'product_purchase',
                    'internal_reference' => $result['internal_reference'] ?? null,
                    'validation_transaction_id' => $validationTransaction['transaction_id'] ?? null
                ])
            ]);

            // Post to webhook if configured
            $this->postToWebhook([
                'transaction_id' => $result['internal_reference'] ?? $this->mobileMoneyService->generateReference(),
                'reference' => $result['internal_reference'] ?? $this->mobileMoneyService->generateReference(),
                'msisdn' => $msisdn,
                'amount' => $amount,
                'status' => 'PENDING',
                'transaction_type' => 'product_purchase',
                'validation_reference' => $json->validation_reference,
                'internal_reference' => $result['internal_reference'] ?? null,
                'created_at' => date('Y-m-d H:i:s')
            ]);
        }

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Debug endpoint to check recent transactions
     * GET /api/mobile-money/debug/transactions
     */
    public function debugTransactions()
    {
        $transactions = $this->paymentTransactionModel->orderBy('created_at', 'DESC')->limit(5)->findAll();
        
        return $this->respond([
            'success' => true,
            'message' => 'Recent transactions',
            'count' => count($transactions),
            'transactions' => $transactions
        ]);
    }

    /**
     * Get comprehensive transaction details
     * GET /api/mobile-money/transaction/{reference}
     */
    public function getTransactionDetails($reference = null)
    {
        if (!$reference) {
            return $this->respond([
                'success' => false,
                'message' => 'Reference is required'
            ], 400);
        }

        $result = $this->transactionManagementService->getTransactionDetails($reference);
        return $this->respond($result, $result['success'] ? 200 : 404);
    }

    /**
     * Initiate chargeback
     * POST /api/mobile-money/chargeback
     */
    public function initiateChargeback()
    {
        $json = $this->request->getJSON();

        if (!$json || !isset($json->transaction_id) || !isset($json->reason)) {
            return $this->respond([
                'success' => false,
                'message' => 'Missing required fields: transaction_id, reason'
            ], 400);
        }

        $result = $this->transactionManagementService->initiateChargeback(
            $json->transaction_id,
            $json->reason,
            $json->additional_data ?? []
        );

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Update chargeback status
     * PUT /api/mobile-money/chargeback/{transaction_id}
     */
    public function updateChargebackStatus($transactionId = null)
    {
        if (!$transactionId) {
            return $this->respond([
                'success' => false,
                'message' => 'Transaction ID is required'
            ], 400);
        }

        $json = $this->request->getJSON();

        if (!$json || !isset($json->status)) {
            return $this->respond([
                'success' => false,
                'message' => 'Missing required field: status'
            ], 400);
        }

        $result = $this->transactionManagementService->updateChargebackStatus(
            $transactionId,
            $json->status,
            $json->reason ?? null
        );

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Process refund
     * POST /api/mobile-money/refund
     */
    public function processRefund()
    {
        $json = $this->request->getJSON();

        if (!$json || !isset($json->transaction_id) || !isset($json->amount)) {
            return $this->respond([
                'success' => false,
                'message' => 'Missing required fields: transaction_id, amount'
            ], 400);
        }

        $result = $this->transactionManagementService->processRefund(
            $json->transaction_id,
            (float) $json->amount,
            $json->reason ?? null
        );

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Update refund status
     * PUT /api/mobile-money/refund/{transaction_id}
     */
    public function updateRefundStatus($transactionId = null)
    {
        if (!$transactionId) {
            return $this->respond([
                'success' => false,
                'message' => 'Transaction ID is required'
            ], 400);
        }

        $json = $this->request->getJSON();

        if (!$json || !isset($json->status)) {
            return $this->respond([
                'success' => false,
                'message' => 'Missing required field: status'
            ], 400);
        }

        $result = $this->transactionManagementService->updateRefundStatus(
            $transactionId,
            $json->status
        );

        return $this->respond($result, $result['success'] ? 200 : 400);
    }

    /**
     * Get chargeback transactions
     * GET /api/mobile-money/chargebacks
     */
    public function getChargebacks()
    {
        $result = $this->transactionManagementService->getChargebackTransactions();
        return $this->respond($result);
    }

    /**
     * Get refund transactions
     * GET /api/mobile-money/refunds
     */
    public function getRefunds()
    {
        $result = $this->transactionManagementService->getRefundTransactions();
        return $this->respond($result);
    }

    /**
     * Generate transaction report
     * GET /api/mobile-money/report?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD
     */
    public function generateReport()
    {
        $startDate = $this->request->getGet('start_date');
        $endDate = $this->request->getGet('end_date');

        if (!$startDate || !$endDate) {
            return $this->respond([
                'success' => false,
                'message' => 'Missing required parameters: start_date, end_date (YYYY-MM-DD format)'
            ], 400);
        }

        // Validate date format
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $startDate) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $endDate)) {
            return $this->respond([
                'success' => false,
                'message' => 'Invalid date format. Use YYYY-MM-DD'
            ], 400);
        }

        $result = $this->transactionManagementService->generateTransactionReport($startDate, $endDate);
        return $this->respond($result);
    }
}
