<?php

namespace App\Http\Controllers\Frontend\Dashboard;

use App\Http\Controllers\Controller;
use App\Models\PlayerRanking;
use App\Services\Analytics\StatsService;
use App\Services\Api\API;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;

class DashboardController extends Controller
{
    protected API $api;


    public function __construct(
        API $api,
        private readonly StatsService $statsService
    ) {
        $this->api = $api;
    }

    private function getRoleBaseCached(int $characterId): ?array
    {
        try {
            $result = $this->api->getRoleBase($characterId);
            return is_array($result) ? $result : null;
        } catch (\Exception $e) {
            return null;
        }
    }

    private function getRoleStatusCached(int $characterId): ?array
    {
        try {
            $result = $this->api->getRoleStatus($characterId);
            return is_array($result) ? $result : null;
        } catch (\Exception $e) {
            return null;
        }
    }

    public function index(): Response
    {
        $user = Auth::user();
        $onlineData = $this->statsService->getOnlineData();
        $timezone = $this->statsService->getServerTimezone();
        $totalAccounts = $this->statsService->getTotalUsers();

        // Get recent topup activities from all payment gateways
        $recentTopups = $this->getRecentTopups();

        // Get user characters (try API first, fallback to database)
        $charactersData = $this->getUserCharacters($user->ID);

        return Inertia::render('frontend/dashboard/index', [
            'stats' => [
                'totalAccounts' => $totalAccounts,
                'onlinePlayers' => $onlineData['count'],
                'onlineGMs' => $onlineData['gms'],
                'serverOnline' => $onlineData['serverOnline'] ?? false,
                'serverTime' => Carbon::now($timezone)->format('H:i:s'),
                'serverDate' => Carbon::now($timezone)->format('d M Y'),
                'timezone' => $timezone,
            ],
            'recentTopups' => $recentTopups,
            'userCharacters' => $charactersData['characters'],
            'charactersFromCache' => $charactersData['fromCache'],
        ]);
    }

    /**
     * Get recent paid topup transactions from all payment gateways
     */
    private function getRecentTopups(): array
    {
        // Combine all transaction tables
        $tripayTransactions = DB::table('tripay_transactions')
            ->select(
                'user_id',
                'character_id',
                'gold_amount',
                'amount',
                'paid_at as created_at',
                DB::raw("'Tripay' as payment_method")
            )
            ->where('status', 'paid')
            ->whereNotNull('paid_at');

        $ipaymuTransactions = DB::table('ipaymu_transactions')
            ->select(
                'user_id',
                'character_id',
                'gold_amount',
                'amount',
                'paid_at as created_at',
                DB::raw("'Ipaymu' as payment_method")
            )
            ->where('status', 'berhasil')  // iPaymu callback sets 'berhasil'
            ->whereNotNull('paid_at');

        $duitkuTransactions = DB::table('duitku_transactions')
            ->select(
                'user_id',
                'character_id',
                'gold_amount',
                'amount',
                'paid_at as created_at',
                DB::raw("'Duitku' as payment_method")
            )
            ->where('status', 'success')  // Duitku callback sets 'success')
            ->whereNotNull('paid_at');

        $pakasirTransactions = DB::table('pakasir_transactions')
            ->select(
                'user_id',
                'character_id',
                'gold_amount',
                'amount',
                'paid_at as created_at',
                DB::raw("'Pakasir' as payment_method")
            )
            ->where('status', 'success')  // Pakasir callback sets 'success')
            ->whereNotNull('paid_at');

        // Union all transactions and get the latest 10
        $transactions = $tripayTransactions
            ->union($ipaymuTransactions)
            ->union($duitkuTransactions)
            ->union($pakasirTransactions)
            ->orderBy('created_at', 'desc')
            ->limit(10)
            ->get();

        // Get character name and user information for each transaction
        $result = [];
        foreach ($transactions as $transaction) {
            $characterName = null;
            $characterClass = null;

            // Get character name and class from API
            if ($transaction->character_id) {
                $roleBase = $this->getRoleBaseCached($transaction->character_id);
                if ($roleBase && isset($roleBase['name'])) {
                    $characterName = $roleBase['name'];
                    $characterClass = $roleBase['cls'] ?? null;
                }

                // Fallback 1: Try player_rankings if API didn't return data
                if (! $characterName) {
                    $character = DB::table('player_rankings')
                        ->where('role_id', $transaction->character_id)
                        ->first();

                    if ($character) {
                        $characterName = $character->role_name;
                        $characterClass = $character->cls;
                    }
                }
            }

            // Fallback 2: Use username if character still not found
            if (! $characterName) {
                $user = DB::table('users')->where('ID', $transaction->user_id)->first();
                $characterName = $user ? $user->truename : 'Unknown';
            }

            $result[] = [
                'username' => $characterName,
                'class' => $characterClass,
                'gold_amount' => $transaction->gold_amount,
                'amount' => $transaction->amount,
                'payment_method' => $transaction->payment_method,
                'created_at' => Carbon::parse($transaction->created_at)->diffForHumans(),
            ];
        }

        return $result;
    }

    /**
     * Get user characters with their status
     * Try API first, fallback to database cache if API fails
     */
    private function getUserCharacters(int $userId): array
    {
        try {
            // Set timeout for API call
            set_time_limit(15);

            $rolesData = $this->api->getRoles($userId);
            $roles = $rolesData['roles'] ?? [];

            $onlineList = $this->api->getOnlineList();
            $onlineRoleIds = array_column($onlineList, 'roleid');

            $characters = [];
            foreach ($roles as $role) {
                $base = $this->getRoleBaseCached($role['id']);
                $status = $this->getRoleStatusCached($role['id']);

                $characters[] = [
                    'id' => $role['id'],
                    'name' => $role['name'],
                    'level' => $status['level'] ?? 0,
                    'class' => $base['cls'] ?? 0,
                    'is_online' => in_array($role['id'], $onlineRoleIds),
                ];
            }

            return [
                'characters' => $characters,
                'fromCache' => false,
            ];
        } catch (\Exception $e) {
            // Silently fallback to database cache
            return [
                'characters' => $this->getUserCharactersFromCache($userId),
                'fromCache' => true,
            ];
        }
    }

    /**
     * Get user characters from database cache (player_rankings)
     */
    private function getUserCharactersFromCache(int $userId): array
    {
        $rankings = PlayerRanking::where('user_id', $userId)
            ->orderBy('level', 'DESC')
            ->orderBy('reputation', 'DESC')
            ->get();

        $characters = [];
        foreach ($rankings as $ranking) {
            $characters[] = [
                'id' => $ranking->role_id,
                'name' => $ranking->role_name,
                'level' => $ranking->level,
                'class' => $ranking->cls,
                'is_online' => false, // Cache data doesn't have online status
            ];
        }

        return $characters;
    }
}
