<?php

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

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\DuitkuSettings;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;

class DuitkuController extends TopUpController
{
    use PaymentServiceTrait, RateLimitingTrait;

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

        if (! $settings) {
            return redirect()->route('dashboard')->with('error', 'Duitku service is currently not available.');
        }

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

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

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

        return Inertia::render('frontend/topup/duitku/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, 'duitku');
        if (! $rateLimit['allowed']) {
            return back()->with('error', $rateLimit['error']);
        }

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

        $settings = DuitkuSettings::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'];

        $merchantOrderId = 'DUITKU-'.time().'-'.$user->ID;

        try {
            // Prepare Duitku API request
            $apiUrl = $settings->production_mode
                ? 'https://passport.duitku.com/webapi/api/merchant/v2/inquiry'
                : 'https://sandbox.duitku.com/webapi/api/merchant/v2/inquiry';

            // Build product name using trait
            $productName = $this->buildProductName($goldAmount, $promoResult);

            $params = [
                'merchantCode' => $settings->merchant_code,
                'paymentAmount' => $promoResult['final_amount'],
                'paymentMethod' => $settings->payment_method, // Use payment method from settings
                'merchantOrderId' => $merchantOrderId,
                'productDetails' => $productName,
                'email' => $user->email ?: 'guest@example.com',
                'phoneNumber' => $user->mobilenumber ?: '08123456789',
                'customerVaName' => $user->name ?: 'Guest',
                'callbackUrl' => rtrim(config('app.url'), '/').'/topup/duitku/callback',
                'returnUrl' => rtrim(config('app.url'), '/').'/topup/duitku/return',
                'expiryPeriod' => 1440,
            ];

            // Generate signature using the model's method
            $signature = $settings->generateSignature($merchantOrderId, $promoResult['final_amount']);
            $params['signature'] = $signature;

            \Log::info('Duitku payment request', [
                'url' => $apiUrl,
                'production_mode' => $settings->production_mode,
                'params' => $params,
            ]);

            // Send request as JSON (Duitku V2 API requires application/json)
            $response = \Http::withHeaders([
                'Content-Type' => 'application/json',
            ])->post($apiUrl, $params);
            $result = $response->json();

            \Log::info('Duitku payment response', ['response' => $result]);

            if (isset($result['statusCode']) && $result['statusCode'] === '00') {
                // Save transaction to database
                DB::table('duitku_transactions')->insert([
                    'user_id' => $user->ID,
                    'character_id' => $request->character_id,
                    'merchant_order_id' => $merchantOrderId,
                    'reference' => $result['reference'] ?? null,
                    'amount' => $promoResult['final_amount'],
                    'gold_amount' => $goldAmount,
                    'payment_method' => $settings->payment_method,
                    'streamer_code' => $streamerResult['streamer'] ? $streamerResult['streamer']->code : null,
                    'status' => 'pending',
                    'payment_url' => $result['paymentUrl'] ?? null,
                    'response_data' => json_encode($result),
                    '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);

                if (isset($result['paymentUrl'])) {
                    return Inertia::location($result['paymentUrl']);
                }
            }

            $errorMsg = $result['statusMessage'] ?? 'Unknown error';

            return back()->with('error', 'Payment error: '.$errorMsg);
        } catch (\Exception $e) {
            $errorResult = $this->handlePaymentException($e, 'Duitku');

            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 handleCallback(Request $request)
    {
        $merchantOrderId = $request->input('merchantOrderId');
        $resultCode = $request->input('resultCode');
        $reference = $request->input('reference');
        $amount = $request->input('amount');
        $signature = $request->input('signature');

        \Log::info('Duitku callback received', $request->all());

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

        // Verify callback signature
        $settings = DuitkuSettings::first();
        if (! $settings) {
            \Log::error('Duitku callback: Settings not found');

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

        // Duitku callback signature format: md5(merchantCode + amount + merchantOrderId + apiKey)
        $expectedSignature = md5($settings->merchant_code.$amount.$merchantOrderId.$settings->api_key);

        if ($signature !== $expectedSignature) {
            \Log::error('Duitku callback signature mismatch', [
                'expected' => $expectedSignature,
                'received' => $signature,
                'merchantOrderId' => $merchantOrderId,
            ]);

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

        $transaction = DB::table('duitku_transactions')
            ->where('merchant_order_id', $merchantOrderId)
            ->first();

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

        // Map Duitku status code
        $newStatus = $resultCode == '00' ? 'success' : ($resultCode == '01' ? 'pending' : 'failed');
        $oldStatus = $transaction->status;

        // Update transaction
        DB::table('duitku_transactions')
            ->where('id', $transaction->id)
            ->update([
                'reference' => $reference,
                'status' => $newStatus,
                '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') {
            $settings = DuitkuSettings::first();
            $user = $this->handlePaymentSuccess($transaction, $settings?->gold_rate);

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

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

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