<?php

namespace App\Http\Controllers\Api;

use Closure;
use Carbon\Carbon;
use App\Models\User;
use App\Models\Market;
use App\Models\AppData;
use App\Models\GameType;
use Illuminate\Support\Str;
use App\Models\MarketRecord;
use App\Models\MarketResult;
use Illuminate\Http\Request;
use App\Models\DesawarMarket;
use App\Models\DesawarRecord;
use App\Models\DesawarResult;
use App\Models\StartLineMarket;
use App\Models\StartLineRecord;
use App\Models\StartLineResult;
use Illuminate\Validation\Rule;
use App\Http\Controllers\Controller;
use App\Models\AgentTransaction;
use App\Models\LevelAmount;
use App\Models\UserLevel;
use App\Notifications\BonusWonNotification;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

class GameController extends Controller
{
    public function getWinnersList()
    {
        //list of records from market_records table where status is success in last 24 hours, random 30 records
        $winners = MarketRecord::where('status', 'success')
            ->where('updated_at', '>', Carbon::now()->subHour())
            // ->where('updated_at', '>', Carbon::now()->subDays(10))
            ->with('market')
            ->with('user')
            ->inRandomOrder()
            ->limit(30)
            ->get();

        return response()->success("Data Sent!", compact('winners'));
    }

    public function submitGame(Request $request)
    {
        Log::info('submitGame', ['request' => $request->all()]);
        $request->validate([
            'type' => ['required', Rule::in(['general', 'startLine', 'desawar'])],
            'market_id' => 'required|numeric',
            //is_total_jodi optional
            // 'is_total_jodi' => 'nullable|sometimes|boolean',
            'games' => [
                'required',
                'array',
                'min:1',
                function (string $attribute, mixed $value, Closure $fail) {
                    foreach ($value as $game) {
                        if (!is_array($game) || !isset($game['number']) || !isset($game['amount']) || !isset($game['session']) || !isset($game['game_type_id'])) {
                            $fail("{$attribute} must be an array of games with number, amount, game_type_id and session.");
                        }
                    }
                },
            ],
            'games.*.number' => [
                'required',
                'string',
                function ($attribute, $value, $fail) {
                    if (!ctype_digit($value)) {
                        $fail('The ' . $attribute . ' must be a numeric string.');
                    }
                }
            ],
            'games.*.amount' => ['required', 'numeric', 'min:5'],
            'games.*.session' => ["required", Rule::in(['open', 'close', 'null'])],
            'games.*.game_type_id' => 'required|exists:game_types,id',
        ]);

        $appData = AppData::first();
        // Check if any amount in games array exceeds 100
        foreach ($request->games as $key => $game) {
            if ($game['amount'] > $appData->max_bid_amount) {
                $message = "Amount in Game Number $key is More Than " . $appData->max_bid_amount . "! Maximum Bid Amount is " . $appData->max_bid_amount;
                return response()->failed($message);
            }
        }

        $market = match ($request->type) {
            "general" => Market::class,
            "startLine" => StartLineMarket::class,
            "desawar" => DesawarMarket::class,
        };
        if (!$market::where('id', $request->market_id)->exists()) {
            $message = "The selected market id is invalid.";
            return response()->failed($message);
        }

        if (!$market::where('id', $request->market_id)->first()->game_on) {
            return response()->failed("Game Is Not Open at The Moment!");
        }

        
        /** @var User $user  */
        $user = auth()->user();
        
        // Check if any amount in games array is less than 1
        foreach ($request->games as $key => $game) {
            if ($game['amount'] < 1) {
                // Log the suspicious activity
                Log::warning('User attempted to submit game with amount less than 1', [
                    'user_id' => $user->id,
                    'user_name' => $user->name,
                    'user_phone' => $user->phone,
                    'market_id' => $request->market_id,
                    'type' => $request->type,
                    'game_number' => $key,
                    'attempted_amount' => $game['amount'],
                    'game_details' => $game,
                    'ip_address' => request()->ip(),
                    'timestamp' => now()
                ]);

                // Block the user
                $user->update(['status' => 'blocked']);

                $message = "Your account has been blocked due to suspicious activity. Invalid amount in Game Number " . ($key + 1) . "! Minimum Bid Amount is ₹1";
                return response()->failed($message);
            }
        }

        $amountSum = array_sum(array_column($request->games, 'amount'));
        
        if ($user->balance < $amountSum) {
            return response()->failed("User's balance is insufficient");
        }

        $marketRecord = match ($request->type) {
            "general" => MarketRecord::class,
            "startLine" => StartLineRecord::class,
            "desawar" => DesawarRecord::class,
        };
        $property_name = match ($request->type) {
            "general" => "market_id",
            "startLine" => "startline_market_id",
            "desawar" => "desawar_market_id",
        };


        // if (isset($request->is_total_jodi) && $request->is_total_jodi) {
        //     $market = $market::find($request->market_id);
        //     $firstGame = $request->games[0];
        //     $newTransaction = $user->transactions()->create([
        //         "previous_amount" => $user->balance,
        //         "amount" => $amountSum,
        //         "current_amount" => $user->balance - $amountSum,
        //         "type" => "play",
        //         // 1st game number
        //         "details" => "Game ( " . Carbon::now() . " : $market->name : Total Jodi ) : $firstGame[number]",
        //     ]);


        // //insert 1 market record for total jodi
        // $marketRecord::create([
        //     "market_id" => $request->market_id,
        //     'game_type_id' => $firstGame['game_type_id'],
        //     $property_name => $request->market_id,
        //     'number' => $firstGame['number'],
        //     'amount' => $amountSum,
        //     'session' => $firstGame['session'],
        //     'status' => "pending",
        //     'user_id' => $user->id,
        //     'game_string' => Str::random(12),
        //     'date' => Carbon::today(),
        //     'transaction_id' => $newTransaction->id,
        //     'is_total_jodi' => 0,
        // ]);
        // }

        foreach ($request->games as $game) {
            if ($request->type == 'desawar' && $game['number'] < 10 && strlen($game['number']) == 1) {
                $game['number'] = '0' . $game['number'];
            }

            $market = $market::find($request->market_id);

            //check if game type is open, if open then check open_game_status
            if (($game['session'] == 'open' || $game['game_type_id'] == 2 || $game['game_type_id'] == 6 || $game['game_type_id'] == 7 || $game['game_type_id'] == 8) && $request->type != 'startLine') {
                if (!$market->open_game_status) {
                    return response()->failed("Open Game is not open at the moment!");
                }
            }

            //check if game type is close, if close then check close_game_status
            if (
                $game['session'] == 'close' && $request->type != 'startLine' && $request->type != 'desawar'
            ) {
                if (!$market->close_game_status) {
                    return response()->failed("Close Game is not open at the moment!");
                }
            }

            $game_type = GameType::find($game['game_type_id']);

            // Limit checks based on game type, market, user, and date
            $enableLimits = false;
            if ($enableLimits) {
                $gameTypeLimits = [
                    'single_digit' => 6,
                    'jodi' => 40,
                    'double_pana' => 40
                ];

                if (array_key_exists($game_type->game_type, $gameTypeLimits)) {
                    $userGameCountQuery = $marketRecord::where('market_id', $request->market_id)
                        ->where('user_id', $user->id)
                        ->where('date', Carbon::today())
                        ->where('game_type_id', $game['game_type_id']);

                    if ($game['session'] == 'open') {
                        $userGameCountQuery->where('session', 'open');
                    } else if ($game['session'] == 'close' || $game['session'] == 'null') {
                        $userGameCountQuery->where('session', 'close')->orWhere('session', 'null');
                    }

                    $userGameCount = $userGameCountQuery->count();

                    if ($userGameCount >= $gameTypeLimits[$game_type->game_type]) {
                        return response()->failed("You have reached the maximum bet limit ({$gameTypeLimits[$game_type->game_type]}) for {$game_type->game_type} today in this market.");
                    }
                }
            }

            //if $game_type->game_type is single_digit then check if number is single digit
            //if $game_type->game_type is jodi_digit then check if number is double digit else return error
            //if $game_type->game_type is single_pana or double_pana or triple_pana then check if number is 3 digit
            if ($game_type->game_type == 'single_digit' && strlen($game['number']) != 1) {
                return response()->failed("Single Digit Game Type Only Accepts Single Digit Number!");
            } elseif ($game_type->game_type == 'jodi' && strlen($game['number']) != 2) {
                return response()->failed("Jodi Game Type Only Accepts Double Digit Number!");
            } elseif (
                in_array($game_type->game_type, ['single_pana', 'double_pana', 'triple_pana']) && strlen($game['number']) != 3
            ) {
                return response()->failed("Pana Game Type Only Accepts Three Digit Number!");
            }

            // if (!isset($request->is_total_jodi) || !$request->is_total_jodi) {
            $newTransaction = $user->transactions()->create([
                "previous_amount" => $user->balance,
                "amount" => $game["amount"],
                "current_amount" => $user->balance - $game["amount"],
                "type" => "play",
                "details" => "Game ( " . Carbon::now() . " : $market->name : $game_type->name ) : $game[number]",
            ]);
            // }

            $marketRecord::create([
                "market_id" => $request->market_id,
                'game_type_id' => $game['game_type_id'],
                $property_name => $request->market_id,
                'number' => $game['number'],
                // 'amount' => $request->is_total_jodi ? $amountSum : $game['amount'],
                'amount' => $game['amount'],
                'session' => $game['session'],
                'status' => "pending",
                'user_id' => $user->id,
                'game_string' => Str::random(12),
                'date' => Carbon::today(),
                'transaction_id' => isset($transaction) ? $newTransaction->id : null,
                // 'is_total_jodi' => $request->is_total_jodi ?? false,
            ]);

            $user->balance -= $game["amount"];
            $user->save();


            // Give Bet Bonus On Five Levels to the user
            $userlevel = UserLevel::where('user_id', $user->id)->first();
            
            if (isset($userlevel) && env('ENABLE_BET_BONUS_Five_LEVELS', false)) {
                for ($i = 1; $i <= 5; $i++) {
                    $level = "user_level_$i";

                    if (isset($userlevel->$level)) {
                        $refferalUser = User::find($userlevel->$level);
                        if (!is_null($refferalUser)) {
                            $balance_before = $refferalUser->balance;

                            $levelAmount = LevelAmount::first();
                            $level1Amount = ($game["amount"] * $levelAmount->level_1_user_amount) / 100;
                            $level2Amount = ($game["amount"] * $levelAmount->level_2_user_amount) / 100;
                            $level3Amount = ($game["amount"] * $levelAmount->level_3_user_amount) / 100;
                            $level4Amount = ($game["amount"] * $levelAmount->level_4_user_amount) / 100;
                            $level5Amount = ($game["amount"] * $levelAmount->level_5_user_amount) / 100;
                            
                            $amount_to_give = 0;
                            switch ($i) {
                                case 1:
                                    $amount_to_give = $level1Amount;
                                    break;
                                case 2:
                                    $amount_to_give = $level2Amount;
                                    break;
                                case 3:
                                    $amount_to_give = $level3Amount;
                                    break;
                                case 4:
                                    $amount_to_give = $level4Amount;
                                    break;
                                case 5:
                                    $amount_to_give = $level5Amount;
                                    break;
                            }                          

                            $refferalUser->balance = $refferalUser->balance + $amount_to_give;
                            $refferalUser->save();

                            // Log::info("========================");
                            // log::info("Giving bonus to user: {$refferalUser->id}, amount: {$amount_to_give}");
                            // Log::info("========================");
                            
                            $refferalUser->transactions()->create([
                                'previous_amount' => $balance_before,
                                'amount' => $amount_to_give,
                                'current_amount' => $refferalUser->balance,
                                "type" => "levelBetCommission",
                                "details" => "You won ($amount_to_give) as a level bet commission."
                            ]);

                            $refferalUser->notify(new BonusWonNotification($amount_to_give, $refferalUser->fcm));
                        }
                    } else {
                        break;
                    }
                }
            }
            
            $user->refresh();

            // giving commission to the agent
            $agent = User::where('id', $user->user_id)->where('role', 'agent')->first();
            if ($agent) {
                $play_percentage = $agent->play_percentage;
                if ($play_percentage > 0) {
                    $agent->balance += $game["amount"] * $play_percentage / 100;
                    $agent->save();

                    $agent_transaction = AgentTransaction::create([
                        'user_id' => $agent->id,
                        'previous_amount' => $agent->balance - $game["amount"] * $play_percentage / 100,
                        'amount' => $game["amount"] * $play_percentage / 100,
                        'current_amount' => $agent->balance,
                        'type' => 'commission',
                        'details' => "Agent Commission from User " . $user->name . " Play",
                    ]);
                }
            }
        }

        $user->refresh();
        $balance_left = $user->balance;
        $message = "Games successfully added";
        return response()->success($message, compact('balance_left'));
    }

    // public function getGameHistory(Request $request)
    // {
    //     $request->validate([
    //         'type' => ['required', Rule::in(['general', 'startLine', 'desawar'])],
    //         'page' => 'required|numeric'
    //     ]);
    //     $market = match ($request->input('type')) {
    //         "general" => MarketRecord::class,
    //         "startLine" => StartLineRecord::class,
    //         "desawar" => DesawarRecord::class,
    //     };
    //     $user = Auth::user();
    //     $gameHistory = $market::with(['market', 'gameType'])
    //         ->where('user_id', $user->id)->latest()->paginate(10, ['*'], 'game_history', $request->page);
    //     return response()->success("Data Sent", compact('gameHistory'));
    // }

    public function getGameHistory(Request $request)
    {
        $request->validate([
            'type' => ['required', Rule::in(['general', 'startLine', 'desawar'])],
            'page' => 'required|numeric'
        ]);

        $market = match ($request->input('type')) {
            "general" => MarketRecord::class,
            "startLine" => StartLineRecord::class,
            "desawar" => DesawarRecord::class,
        };

        $user = Auth::user();

        $query = $market::with(['market', 'gameType'])
            ->where('user_id', $user->id);

        // Apply condition only for MarketRecord::class
        // if ($market === MarketRecord::class) {
        //     $query->where('is_total_jodi', 0);
        // }

        $gameHistory = $query->latest()->paginate(10, ['*'], 'game_history', $request->page);

        return response()->success("Data Sent", compact('gameHistory'));
    }


    public function getGameResults(Request $request)
    {
        $request->validate([
            'type' => ['required', Rule::in(['general', 'startLine', 'desawar'])],
            'date' => 'date|nullable|sometimes'
        ]);
        $market = match ($request->input('type')) {
            "general" => MarketResult::class,
            "startLine" => StartLineResult::class,
            "desawar" => DesawarResult::class,
        };

        $date = $request->input('date') ?? Carbon::today();
        $gameResults = $market::with('market')
            ->where('result_date', $date)
            ->get();
        return response()->success("Data Sent!", compact('gameResults'));
    }

    public function getGameRates()
    {
        $appData = AppData::first();
        $gameTypesGeneral = GameType::where('type', 'general')->get();
        $gameTypesStartLine = GameType::where('type', 'start_line')->get();
        $gameTypesDesawar = GameType::where('type', 'desawar')->get();

        // $data = [
        //     $data1 = [
        //         'title' => 'Game Win Ratio for All Bids',
        //         'list' => $gameTypesGeneral
        //     ],
        //     $data2 = [
        //         'title' => 'King Starline Game Win Ration',
        //         'list' => $gameTypesStartLine
        //     ],
        //     $data3 = [
        //         'title' => 'Desawar Game Win Ratio',
        //         'list' => $gameTypesDesawar
        //     ],
        // ];
        //if appData-enable_desawara_ony is true then only send desawar data

        $data = [];
        if ($appData->enable_desawar_only) {
            $data = [
                $data1 = [
                    'title' => 'Desawar Game Win Ratio',
                    'list' => $gameTypesDesawar
                ],
            ];
        } else {
            //if enable_desawar then send all data else send general and startline data
            if ($appData->enable_desawar) {
                $data = [
                    $data1 = [
                        'title' => 'Game Win Ratio for All Bids',
                        'list' => $gameTypesGeneral
                    ],
                    $data2 = [
                        'title' => 'King Starline Game Win Ration',
                        'list' => $gameTypesStartLine
                    ],
                    $data3 = [
                        'title' => 'Desawar Game Win Ratio',
                        'list' => $gameTypesDesawar
                    ],
                ];
            } else {
                $data = [
                    $data1 = [
                        'title' => 'Game Win Ratio for All Bids',
                        'list' => $gameTypesGeneral
                    ],
                    $data2 = [
                        'title' => 'King Starline Game Win Ration',
                        'list' => $gameTypesStartLine
                    ],
                ];
            }
        }

        return response()->success("Data Sent!", compact('data'));
    }
}
