<?php

namespace App\Http\Controllers;

use App\Mail\PaymentSuccessMail;
use App\Models\CoinTransaction;
use App\Services\PaymentGatewayService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;

class PaymentCallbackController extends Controller
{
    public function __construct(
        protected PaymentGatewayService $paymentGatewayService
    ) {}

    /**
     * Handle payment callback from payment gateway.
     */
    public function handleCallback(Request $request)
    {
        try {
            // Log the callback request for debugging
            Log::info('Payment Callback Received', [
                'data' => $request->all(),
                'headers' => $request->headers->all(),
            ]);

            // Get reference code from callback
            $referenceCode = $request->input('ref') ?? $request->input('ref_kode') ?? $request->input('reference_code');

            if (! $referenceCode) {
                Log::warning('Payment Callback: Missing reference code', [
                    'request_data' => $request->all(),
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Missing reference code',
                ], 400);
            }

            // Find transaction by reference code
            $transaction = CoinTransaction::where('reference_code', $referenceCode)
                ->orWhere('payment_reference', $referenceCode)
                ->first();

            if (! $transaction) {
                Log::warning('Payment Callback: Transaction not found', [
                    'reference_code' => $referenceCode,
                ]);

                return response()->json([
                    'success' => false,
                    'message' => 'Transaction not found',
                ], 404);
            }

            // Verify transaction status with payment gateway
            $statusResult = $this->paymentGatewayService->getTransactionStatus(
                $referenceCode,
                $request->input('ref_id')
            );

            // Update transaction with callback data
            $transaction->update([
                'callback_data' => $request->all(),
                'status' => $this->mapPaymentStatus($request->input('status', 'pending')),
            ]);

            // If payment is successful, add coins to user
            if ($statusResult['success'] && isset($statusResult['data']['status'])) {
                $paymentStatus = $this->mapPaymentStatus($statusResult['data']['status']);

                if ($paymentStatus === 'success' && ! $transaction->isSuccess()) {
                    DB::transaction(function () use ($transaction) {
                        // Mark transaction as success
                        $transaction->markAsSuccess();

                        // Add coins to user balance
                        $transaction->user->addCoins($transaction->coins);

                        Log::info('Payment Success: Coins added to user', [
                            'transaction_id' => $transaction->id,
                            'user_id' => $transaction->user_id,
                            'coins' => $transaction->coins,
                        ]);
                    });

                    // Log payment success activity
                    $transaction->refresh();
                    $this->activityLogService->logPaymentSuccess(
                        $transaction,
                        "Payment successful for transaction #{$transaction->id}, {$transaction->coins} coins added to user balance",
                        [
                            'amount' => $transaction->amount,
                            'coins' => $transaction->coins,
                            'fee' => $transaction->fee,
                            'payment_channel' => $transaction->payment_channel,
                            'reference_code' => $transaction->reference_code,
                        ]
                    );

                    // Send success email
                    try {
                        Mail::to($transaction->user->email)->send(new PaymentSuccessMail($transaction));
                    } catch (\Exception $e) {
                        Log::error('Failed to send payment success email', [
                            'transaction_id' => $transaction->id,
                            'user_id' => $transaction->user_id,
                            'error' => $e->getMessage(),
                        ]);
                        // Don't fail the callback if email fails
                    }
                } elseif ($paymentStatus === 'failed' && ! $transaction->isFailed()) {
                    $transaction->markAsFailed();

                    Log::info('Payment Failed', [
                        'transaction_id' => $transaction->id,
                        'user_id' => $transaction->user_id,
                    ]);
                }
            }

            return response()->json([
                'success' => true,
                'message' => 'Callback processed successfully',
            ]);
        } catch (\Exception $e) {
            Log::error('Payment Callback Error', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'request_data' => $request->all(),
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Internal server error',
            ], 500);
        }
    }

    /**
     * Map payment gateway status to our transaction status.
     */
    protected function mapPaymentStatus(?string $status): string
    {
        return match (strtolower($status ?? '')) {
            'paid', 'success', 'completed', 'settled' => 'success',
            'pending', 'processing', 'waiting' => 'processing',
            'failed', 'error', 'canceled', 'cancelled' => 'failed',
            'expired' => 'cancelled',
            default => 'pending',
        };
    }
}
