<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\LedgerTransaction;
use App\Models\Wallet;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class PaystackWebhookController extends Controller
{
    /**
     * Handle Paystack webhook events
     */
    public function handleWebhook(Request $request): JsonResponse
    {
        try {
            // Verify webhook signature
            $payload = $request->getContent();
            $signature = $request->header('X-Paystack-Signature');
            
            if (!$this->verifyWebhookSignature($payload, $signature)) {
                Log::warning('Invalid Paystack webhook signature', [
                    'signature' => $signature,
                    'payload' => $payload
                ]);
                return response()->json(['message' => 'Invalid signature'], 400);
            }

            $event = $request->input('event');
            $data = $request->input('data');

            Log::info('Paystack webhook received', [
                'event' => $event,
                'data' => $data
            ]);

            switch ($event) {
                case 'charge.success':
                    return $this->handleChargeSuccess($data);
                    
                case 'transfer.success':
                    return $this->handleTransferSuccess($data);
                    
                case 'transfer.failed':
                    return $this->handleTransferFailed($data);
                    
                case 'invoice.create':
                    return $this->handleInvoiceCreate($data);
                    
                case 'invoice.update':
                    return $this->handleInvoiceUpdate($data);
                    
                default:
                    Log::info('Unhandled Paystack event', ['event' => $event]);
                    return response()->json(['message' => 'Event handled'], 200);
            }
        } catch (\Exception $e) {
            Log::error('Paystack webhook error: ' . $e->getMessage(), [
                'request' => $request->all(),
                'exception' => $e
            ]);
            return response()->json(['message' => 'Error processing webhook'], 500);
        }
    }

    /**
     * Handle successful charge (deposit)
     */
    private function handleChargeSuccess(array $data): JsonResponse
    {
        try {
            $reference = $data['reference'];
            $amount = $data['amount'] / 100; // Convert from kobo to main currency
            $currency = $data['currency'] ?? 'KES';
            $customerEmail = $data['customer']['email'] ?? null;
            $metadata = $data['metadata'] ?? [];

            // Find existing transaction by reference
            $existingTransaction = LedgerTransaction::where('external_reference', $reference)->first();
            
            if ($existingTransaction) {
                Log::info('Transaction already processed', ['reference' => $reference]);
                return response()->json(['message' => 'Transaction already processed'], 200);
            }

            // Get user ID from metadata or find by email
            $userId = $metadata['user_id'] ?? null;
            if (!$userId && $customerEmail) {
                $user = \App\Models\User::where('email', $customerEmail)->first();
                $userId = $user->id ?? null;
            }

            if (!$userId) {
                Log::error('User not found for deposit', [
                    'reference' => $reference,
                    'email' => $customerEmail
                ]);
                return response()->json(['message' => 'User not found'], 400);
            }

            // Process the deposit
            DB::transaction(function () use ($userId, $amount, $currency, $reference, $data) {
                // Create ledger transaction
                $transaction = LedgerTransaction::create([
                    'user_id' => $userId,
                    'type' => 'deposit',
                    'amount' => $amount,
                    'currency' => $currency,
                    'status' => 'completed',
                    'description' => "Paystack deposit via {$data['channel']}",
                    'external_reference' => $reference,
                    'transaction_hash' => $data['authorization']['authorization_code'] ?? null,
                    'details' => [
                        'paystack_reference' => $reference,
                        'channel' => $data['channel'],
                        'ip_address' => $data['ip_address'] ?? null,
                        'metadata' => $data['metadata'] ?? [],
                    ]
                ]);

                // Update wallet balance
                $wallet = Wallet::firstOrCreate([
                    'user_id' => $userId,
                    'currency' => $currency,
                ], [
                    'total_balance' => 0,
                    'available_balance' => 0,
                    'locked_balance' => 0,
                    'settled_balance' => 0,
                ]);

                $wallet->increment('total_balance', $amount);
                $wallet->increment('available_balance', $amount);
                $wallet->save();

                Log::info('Deposit processed successfully', [
                    'user_id' => $userId,
                    'amount' => $amount,
                    'currency' => $currency,
                    'reference' => $reference
                ]);
            });

            // CRITICAL FIX: Sync to Firebase for mobile app real-time update
            $this->syncDepositToFirebase($userId, $amount, $reference);

            return response()->json(['message' => 'Deposit processed successfully'], 200);
        } catch (\Exception $e) {
            Log::error('Error processing charge success: ' . $e->getMessage(), [
                'data' => $data,
                'exception' => $e
            ]);
            return response()->json(['message' => 'Error processing deposit'], 500);
        }
    }

    /**
     * Sync successful deposit to Firebase for mobile app real-time updates
     */
    private function syncDepositToFirebase(int $userId, float $amount, string $reference): void
    {
        try {
            // Check if Firebase is configured
            if (!config('firebase.projects.main.database.url')) {
                Log::warning('Firebase not configured - skipping sync', ['user_id' => $userId]);
                return;
            }

            // Initialize Firebase
            $firebase = app('firebase.database');
            
            // Update user's main wallet balance in Firebase
            $userRef = $firebase->getReference('users/' . $userId);
            $userRef->update([
                'mainWalletBalance' => ['op' => 'increment', 'value' => $amount],
                'balance' => ['op' => 'increment', 'value' => $amount],
                'updatedAt' => FieldValue::serverTimestamp(),
            ]);

            // Create transaction record in Firebase
            $transactionsRef = $firebase->getReference('transactions');
            $newTransactionRef = $transactionsRef->push();
            $newTransactionRef->set([
                'userId' => $userId,
                'type' => 'deposit',
                'amount' => $amount,
                'currency' => 'KES',
                'status' => 'completed',
                'reference' => $reference,
                'wallet' => 'main',
                'paymentMethod' => 'paystack_mobile_money',
                'timestamp' => FieldValue::serverTimestamp(),
            ]);

            // Mark as synced in local database
            $transaction = LedgerTransaction::where('external_reference', $reference)->first();
            if ($transaction) {
                $transaction->update(['firebase_synced_at' => now()]);
            }

            Log::info('Firebase sync completed successfully', [
                'user_id' => $userId,
                'amount' => $amount,
                'reference' => $reference
            ]);
        } catch (\Exception $e) {
            // Log error but don't fail the entire transaction
            // The Laravel deposit succeeded, Firebase sync can be retried
            Log::error('Firebase sync failed: ' . $e->getMessage(), [
                'user_id' => $userId,
                'amount' => $amount,
                'reference' => $reference,
                'exception' => $e
            ]);

            // Queue for retry
            dispatch(new \App\Jobs\RetryFirebaseSync(
                $userId,
                $amount,
                $reference,
                'deposit'
            ))->delay(now()->addMinutes(5));
        }
    }

    /**
     * Handle successful transfer (withdrawal)
     */
    private function handleTransferSuccess(array $data): JsonResponse
    {
        try {
            $reference = $data['reference'];
            $amount = $data['amount'] / 100; // Convert from kobo
            $currency = $data['currency'] ?? 'KES';
            $recipientCode = $data['recipient']['recipient_code'] ?? null;

            // Find the withdrawal transaction
            $transaction = LedgerTransaction::where('external_reference', $reference)
                ->where('type', 'withdrawal')
                ->first();

            if (!$transaction) {
                Log::warning('Withdrawal transaction not found', ['reference' => $reference]);
                return response()->json(['message' => 'Transaction not found'], 404);
            }

            // Update transaction status
            $transaction->update([
                'status' => 'completed',
                'details' => array_merge($transaction->details ?? [], [
                    'paystack_transfer_id' => $data['id'],
                    'transfer_code' => $data['transfer_code'],
                    'status' => $data['status'],
                ])
            ]);

            Log::info('Withdrawal completed successfully', [
                'transaction_id' => $transaction->id,
                'reference' => $reference,
                'amount' => $amount
            ]);

            return response()->json(['message' => 'Withdrawal completed'], 200);
        } catch (\Exception $e) {
            Log::error('Error processing transfer success: ' . $e->getMessage(), [
                'data' => $data,
                'exception' => $e
            ]);
            return response()->json(['message' => 'Error processing withdrawal'], 500);
        }
    }

    /**
     * Handle failed transfer
     */
    private function handleTransferFailed(array $data): JsonResponse
    {
        try {
            $reference = $data['reference'];
            
            $transaction = LedgerTransaction::where('external_reference', $reference)
                ->where('type', 'withdrawal')
                ->first();

            if (!$transaction) {
                Log::warning('Withdrawal transaction not found for failure', ['reference' => $reference]);
                return response()->json(['message' => 'Transaction not found'], 404);
            }

            // Update transaction status and release funds
            DB::transaction(function () use ($transaction, $data) {
                $transaction->update([
                    'status' => 'failed',
                    'details' => array_merge($transaction->details ?? [], [
                        'failure_reason' => $data['reason'] ?? 'Unknown',
                        'paystack_error' => $data['error'] ?? null,
                    ])
                ]);

                // Release locked funds back to available balance
                $wallet = Wallet::where('user_id', $transaction->user_id)
                    ->where('currency', $transaction->currency)
                    ->first();

                if ($wallet) {
                    $wallet->decrement('locked_balance', $transaction->amount);
                    $wallet->increment('available_balance', $transaction->amount);
                    $wallet->save();
                }
            });

            Log::info('Withdrawal failed and funds released', [
                'transaction_id' => $transaction->id,
                'reference' => $reference,
                'reason' => $data['reason'] ?? 'Unknown'
            ]);

            return response()->json(['message' => 'Withdrawal failure processed'], 200);
        } catch (\Exception $e) {
            Log::error('Error processing transfer failure: ' . $e->getMessage(), [
                'data' => $data,
                'exception' => $e
            ]);
            return response()->json(['message' => 'Error processing withdrawal failure'], 500);
        }
    }

    /**
     * Handle invoice creation
     */
    private function handleInvoiceCreate(array $data): JsonResponse
    {
        Log::info('Invoice created', ['data' => $data]);
        return response()->json(['message' => 'Invoice event received'], 200);
    }

    /**
     * Handle invoice update
     */
    private function handleInvoiceUpdate(array $data): JsonResponse
    {
        Log::info('Invoice updated', ['data' => $data]);
        return response()->json(['message' => 'Invoice update received'], 200);
    }

    /**
     * Verify Paystack webhook signature
     */
    private function verifyWebhookSignature(string $payload, string $signature): bool
    {
        $secretKey = config('services.paystack.secret_key');
        
        if (!$secretKey) {
            Log::error('Paystack secret key not configured');
            return false;
        }

        $expectedSignature = hash_hmac('sha512', $payload, $secretKey);
        return hash_equals($expectedSignature, $signature);
    }
}