<?php

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

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

class TripayController extends TopUpController
{
    use PaymentServiceTrait, RateLimitingTrait;

    public function index()
    {
        $user = Auth::user();
        $settings = DB::table('tripay_settings')->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', 'Tripay service is currently not available.');
        }

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

        return Inertia::render('frontend/topup/tripay/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, 'tripay');
        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 = DB::table('tripay_settings')->first();

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

        // Validate and format phone number for Tripay
        $phoneNumber = $user->mobilenumber;
        $phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber);

        if (substr($phoneNumber, 0, 2) === '62') {
            $phoneNumber = '0'.substr($phoneNumber, 2);
        } elseif (substr($phoneNumber, 0, 1) !== '0') {
            $phoneNumber = '0'.$phoneNumber;
        }

        if (strlen($phoneNumber) < 10 || strlen($phoneNumber) > 13) {
            return back()->with('error', 'Invalid phone number format. Please update your phone number in Profile Settings (format: 08xxxxxxxxxx).');
        }

        // 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'];

        $merchantRef = 'TRIPAY-'.time().'-'.$user->ID;

        try {
            // Prepare Tripay API request
            $apiUrl = $settings->production_mode
                ? 'https://tripay.co.id/api/transaction/create'
                : 'https://tripay.co.id/api-sandbox/transaction/create';

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

            // Generate signature
            $signatureData = $settings->merchant_code.$merchantRef.$promoResult['final_amount'];
            $signature = hash_hmac('sha256', $signatureData, $settings->private_key);

            $params = [
                'method' => $settings->payment_method ?? 'BRIVA',
                'merchant_ref' => $merchantRef,
                'amount' => $promoResult['final_amount'],
                'customer_name' => $user->name ?: 'Guest',
                'customer_email' => $user->email ?: 'guest@example.com',
                'customer_phone' => $phoneNumber,
                'order_items' => [
                    [
                        'sku' => 'GOLD-'.$goldAmount,
                        'name' => $productName,
                        'price' => $promoResult['final_amount'],
                        'quantity' => 1,
                    ],
                ],
                'return_url' => rtrim(config('app.url'), '/').'/topup/tripay/return',
                'expired_time' => time() + (24 * 60 * 60),
                'signature' => $signature,
            ];

            \Log::info('Tripay payment request', $params);

            $curl = curl_init();
            curl_setopt_array($curl, [
                CURLOPT_FRESH_CONNECT => true,
                CURLOPT_URL => $apiUrl,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_HEADER => false,
                CURLOPT_HTTPHEADER => [
                    'Authorization: Bearer '.$settings->api_key,
                    'Content-Type: application/json',
                ],
                CURLOPT_FAILONERROR => false,
                CURLOPT_POST => true,
                CURLOPT_POSTFIELDS => json_encode($params),
                CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
            ]);

            $response = curl_exec($curl);
            $error = curl_error($curl);
            curl_close($curl);

            if ($error) {
                \Log::error('Tripay curl error', ['error' => $error]);

                return back()->with('error', 'Payment error: '.$error);
            }

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

            if (isset($result['success']) && $result['success'] && isset($result['data'])) {
                $data = $result['data'];

                // Save transaction to database
                DB::table('tripay_transactions')->insert([
                    'user_id' => $user->ID,
                    'character_id' => $request->character_id,
                    'reference' => $data['reference'],
                    'merchant_ref' => $merchantRef,
                    'amount' => $promoResult['final_amount'],
                    'gold_amount' => $goldAmount,
                    'payment_method' => $params['method'],
                    'streamer_code' => $streamerResult['streamer'] ? $streamerResult['streamer']->code : null,
                    'status' => 'pending',
                    'payment_url' => $data['payment_url'] ?? null,
                    'checkout_url' => $data['checkout_url'] ?? 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);

                $checkoutUrl = $data['checkout_url'] ?? $data['payment_url'] ?? null;
                if ($checkoutUrl) {
                    return Inertia::location($checkoutUrl);
                }
            }

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

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

            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)
    {
        $json = $request->getContent();
        $data = json_decode($json, true);

        \Log::info('Tripay callback received', $data);

        if (! isset($data['reference']) || ! isset($data['status'])) {
            return response()->json(['success' => false, 'message' => 'Invalid callback'], 400);
        }

        // Verify callback signature
        $settings = DB::table('tripay_settings')->first();
        if (! $settings) {
            return response()->json(['success' => false, 'message' => 'Settings not found'], 400);
        }

        $callbackSignature = $request->header('X-Callback-Signature');
        $signature = hash_hmac('sha256', $json, $settings->private_key);

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

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

        $transaction = DB::table('tripay_transactions')
            ->where('reference', $data['reference'])
            ->first();

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

        $newStatus = strtolower($data['status']);
        $oldStatus = $transaction->status;

        // Update transaction
        DB::table('tripay_transactions')
            ->where('id', $transaction->id)
            ->update([
                'status' => $newStatus,
                'response_data' => json_encode($data),
                'updated_at' => now(),
                'paid_at' => $newStatus === 'paid' ? now() : $transaction->paid_at,
            ]);

        // If payment successful, add gold to user using trait
        if ($newStatus === 'paid' && $oldStatus !== 'paid') {
            $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('Tripay donation broadcast sent', [
                        'user' => $user->name,
                        'amount' => $transaction->amount,
                        'gold' => $transaction->gold_amount,
                        'channel' => $channel,
                    ]);
                } catch (\Exception $e) {
                    \Log::error('Failed to send Tripay 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 Tripay Discord notification', [
                        'error' => $e->getMessage(),
                    ]);
                }
            }
        }

        return response()->json(['success' => true]);
    }
}
