<?php

namespace App\Http\Controllers\Frontend\TopUp\Pakasir;

use App\Http\Controllers\Frontend\TopUp\TopUpController;
use App\Http\Controllers\Frontend\TopUp\Traits\PaymentServiceTrait;
use App\Http\Controllers\Frontend\TopUp\Traits\RateLimitingTrait;
use App\Models\PakasirSettings;
use App\Models\PakasirTransaction;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Inertia\Inertia;

class PakasirController extends TopUpController
{
    use PaymentServiceTrait, RateLimitingTrait;

    public function index()
    {
        $user = Auth::user();
        $settings = PakasirSettings::first();

        // Check if game server is online
        $serverOnline = $this->api->serverOnline();

        // Check if service is active
        if (! $settings || ! $settings->is_active) {
            return redirect()->route('dashboard')->with('error', 'Pakasir service is currently not available.');
        }

        $characters = $this->getUserCharactersWithFactionBonus();
        $goldRate = $settings->gold_rate ?? 1000;
        $packages = $this->generatePackages($goldRate);

        return Inertia::render('frontend/topup/pakasir/index', [
            'characters' => $characters,
            'packages' => $packages,
            'settings' => [
                'gold_rate' => $settings->gold_rate,
                'min_amount' => $settings->min_amount,
                'max_amount' => $settings->max_amount,
                'is_active' => (bool) $settings->is_active,
            ],
            'userGold' => $user->gold ?? 0,
            'serverOnline' => $serverOnline,
        ]);
    }

    public function createPayment(Request $request)
    {
        $user = Auth::user();

        // Rate limiting using trait
        $rateLimit = $this->checkPaymentRateLimit($user->ID, 'pakasir');
        if (! $rateLimit['allowed']) {
            return back()->with('error', $rateLimit['error']);
        }

        $request->validate([
            'character_id' => 'required|integer',
            'amount' => 'required|integer|min:1000',
            'promo_code' => 'nullable|string',
        ]);

        $settings = PakasirSettings::first();

        // Validate payment request using trait
        $validation = $this->validatePaymentRequest($user, $settings, $request->amount);
        if (! $validation['valid']) {
            return back()->with('error', $validation['error']);
        }

        // Prepare payment data using trait
        $paymentData = $this->preparePaymentData($request, $user, $settings);
        if (! $paymentData['success']) {
            return back()->with('error', $paymentData['error']);
        }

        $goldAmount = $paymentData['goldAmount'];
        $promoResult = $paymentData['promoResult'];
        $autoPromoResult = $paymentData['autoPromoResult'];
        $streamerResult = $paymentData['streamerResult'];
        $factionData = $paymentData['factionData'];

        $referenceId = 'TOPUP-'.strtoupper(Str::random(12));

        // Log calculation using trait
        $this->logPaymentCalculation(
            $request->character_id,
            $factionData,
            $request->amount,
            $settings->gold_rate,
            $promoResult,
            $streamerResult,
            $goldAmount,
            $autoPromoResult
        );

        try {

            // Generate payment redirect URL with QRIS only
            $redirectUrl = $settings->generatePaymentUrl(
                $promoResult['final_amount'],
                $referenceId,
                rtrim(config('app.url'), '/').'/topup/pakasir/return'
            );

            // Save transaction to database
            DB::table('pakasir_transactions')->insert([
                'user_id' => $user->ID,
                'character_id' => $request->character_id,
                'transaction_id' => null,
                'reference_id' => $referenceId,
                'amount' => $promoResult['final_amount'],
                'gold_amount' => $goldAmount,
                'streamer_code' => $streamerResult['streamer'] ? $streamerResult['streamer']->code : null,
                'payment_method' => 'qris',
                'payment_channel' => 'qris',
                'status' => 'pending',
                'payment_url' => $redirectUrl,
                'response_data' => json_encode(['url' => $redirectUrl]),
                'expired_at' => now()->addHours(24),
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            // Record promo usage using trait
            $this->recordPromoUsage($promoResult, $user->ID);
            $this->recordAutoPromoUsage($autoPromoResult, $user->ID);

            return Inertia::location($redirectUrl);
        } catch (\Exception $e) {
            $errorResult = $this->handlePaymentException($e, 'Pakasir');

            return back()->with('error', $errorResult['error']);
        }
    }

    public function handleReturn(Request $request)
    {
        return redirect()->route('topup.history')->with('info', 'Payment processed. Please wait for confirmation.');
    }

    public function handleNotify(Request $request)
    {

        $amount = $request->input('amount');
        $orderId = $request->input('order_id');
        $status = $request->input('status');
        $project = $request->input('project');
        $paymentMethod = $request->input('payment_method');

        if (! $orderId || ! $amount) {
            return response()->json(['status' => 'error', 'message' => 'Invalid webhook'], 400);
        }

        $settings = PakasirSettings::first();

        if (! $settings || $settings->slug !== $project) {
            \Log::error('Pakasir webhook: Invalid project', [
                'received' => $project,
                'expected' => $settings?->slug,
            ]);

            return response()->json(['status' => 'error', 'message' => 'Invalid project'], 400);
        }

        $transaction = DB::table('pakasir_transactions')
            ->where('reference_id', $orderId)
            ->first();

        if (! $transaction) {
            \Log::error('Pakasir webhook: Transaction not found', [
                'order_id' => $orderId,
            ]);

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

        // Verify amount
        if ((int) $amount !== $transaction->amount) {
            \Log::error('Pakasir webhook: Amount mismatch', [
                'received' => $amount,
                'expected' => $transaction->amount,
            ]);

            return response()->json(['status' => 'error', 'message' => 'Amount mismatch'], 400);
        }

        // SECURITY: Verify payment status via Pakasir API before processing
        // This prevents fake webhooks from exploiting the system
        if ($status === 'completed' || $status === 'success') {
            try {
                $apiResponse = $settings->getTransactionDetail($orderId, (int) $amount);
                $apiStatus = $apiResponse['transaction']['status'] ?? $apiResponse['status'] ?? null;
                if (! $apiResponse || $apiStatus !== 'completed') {
                    \Log::error('Pakasir webhook: API verification failed - payment not confirmed', [
                        'order_id' => $orderId,
                        'webhook_status' => $status,
                        'api_status' => $apiStatus,
                    ]);

                    return response()->json(['status' => 'error', 'message' => 'Payment not verified'], 400);
                }
            } catch (\Exception $e) {
                \Log::error('Pakasir webhook: API verification exception', [
                    'order_id' => $orderId,
                    'error' => $e->getMessage(),
                ]);
                // Allow processing if API is temporarily unavailable but log the warning
                \Log::warning('Pakasir webhook: Proceeding without API verification due to API error');
            }
        }

        $newStatus = PakasirTransaction::mapPakasirStatus($status);
        $oldStatus = $transaction->status;

        // Update transaction
        DB::table('pakasir_transactions')
            ->where('id', $transaction->id)
            ->update([
                'transaction_id' => $orderId,
                'status' => $newStatus,
                'payment_method' => $paymentMethod ?? 'qris',
                'response_data' => json_encode($request->all()),
                'updated_at' => now(),
                'paid_at' => $newStatus === 'success' ? now() : $transaction->paid_at,
            ]);

        // If payment successful, add gold to user using trait
        if ($newStatus === 'success' && $oldStatus !== 'success') {
            $transactionModel = \App\Models\PakasirTransaction::find($transaction->id);
            $user = $this->handlePaymentSuccess($transactionModel, $settings?->gold_rate);

            // Send broadcast notification if enabled
            if ($user && $settings && ($settings->broadcast_enabled ?? true)) {
                try {
                    $message = $settings->getBroadcastMessage($user, $transactionModel);
                    $channel = $settings->broadcast_channel ?? 9;
                    $this->api->WorldChat(0, $message, $channel);
                } catch (\Exception $e) {
                    \Log::error('Failed to send Pakasir donation broadcast', [
                        'error' => $e->getMessage(),
                    ]);
                }
            }

            // Send Discord notification if enabled
            if ($user && $settings && ($settings->discord_enabled ?? false)) {
                try {
                    $settings->sendDiscordNotification($user, $transactionModel);
                } catch (\Exception $e) {
                    \Log::error('Failed to send Pakasir Discord notification', [
                        'error' => $e->getMessage(),
                    ]);
                }
            }
        }

        return response()->json(['status' => 'ok']);
    }

    public function handleCancel(Request $request)
    {
        return redirect()->route('topup.history')->with('error', 'Payment was cancelled.');
    }
}
