<?php

namespace App\Http\Controllers;

use App\Models\Betting;
use App\Models\Commission;
use App\Models\GameId;
use App\Models\GamePoints;
use App\Models\PaymentSettings;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;

class GameController extends Controller
{

    protected function getGamePointRelationship($tab)
    {
        switch ($tab) {
            case 'one_minute':
                return 'gamePoint';
            case 'two_minute':
                return 'gamePoint2Minute';
            case 'three_minute':
                return 'gamePoint3Minute';
            case 'five_minute':
                return 'gamePoint5Minute';
            default:
                return '';
        }
    }

    // function to reply to route /mine/win/getUserResult
    public function GetUserResultData($gameId)
    {
        $tab = request()->input('tab');
        $game = GameId::where('game_id', $gameId)
            ->orderBy('id', 'desc')
            ->first();
        //if game status=0 then wait for 2 seconds
        if ($game->status == 0) {
            sleep(2);
            $game->refresh();
            if ($game->status == 0) {
                sleep(2);
            }
            $game->refresh();
        }

        // Check if the user has placed a bet
        $hasBet = Betting::where('user_id', auth()->id())
            ->where('game_id', $gameId)
            ->where('tab', $tab)
            ->exists();

        // Calculate the winning amount
        $winingAmount = Betting::where('user_id', auth()->id())
            ->where('game_id', $gameId)
            ->where('tab', $tab)
            ->sum('winning_amount');
        $tab_code = $tab . '_code';
        $gamePoints = $game->{$this->getGamePointRelationship($tab)};

        return response()->json([
            'gameId' => $game->game_id,
            'hasBet' => $hasBet,
            'winingAmount' => $winingAmount,
            'tab' => $tab,
            'result' => $game->$tab_code,
            'color' => $gamePoints->color
        ]);
    }

    public function Trend($type)
    {
        // return 'hi';
        $time_interval = 1;
        $typeText = "1 Minute";
        if ($type == "three_minute") {
            $typeText = "3 Minute";
            $time_interval = 3;
        } else if ($type == "five_minute") {
            $typeText = "5 Minute";
            $time_interval = 5;
        } else if ($type == "two_minute") {
            $typeText = "2 Minute";
            $time_interval = 2;
        }
        $green_array = [1, 3, 7, 9];
        $red_array = [2, 4, 6, 8];

        $type_text = $type . '_code';

        $last_two_games = GameId::where(['type' => $type])->orderBy('id', 'desc')->limit(2)->get();
        if (in_array($last_two_games[1]->$type_text, $green_array)) {
            $last_two_games[1]->class = 'item-green';
        } else if (in_array($last_two_games[1]->$type_text, $red_array)) {
            $last_two_games[1]->class = 'item-red';
        } else if ($last_two_games[1]->$type_text == 0) {
            $last_two_games[1]->class = 'item-violet-red';
        } else if ($last_two_games[1]->$type_text == 5) {
            $last_two_games[1]->class = 'item-violet-green';
        }
        $last_two_games[1]->code = $last_two_games[1]->$type_text;
        $all_games = GameId::where(['status' => 1])
            ->whereDate('created_at', Carbon::today())
            ->select("*", "$type_text as code")
            ->where('type', $type)
            ->orderBy('id', 'desc')->get();

        // return $all_games;

        $new_reference = [];
        $total_green_count = 0;
        //-1 qki client dimag kha rha tha
        $total_red_count = -1;
        $total_violet_count = 0;
        foreach ($all_games as $key => $game) {
            if (in_array($game->$type_text, $green_array)) {
                $all_games[$key]->class = 'item-green';
                ++$total_green_count;
            } else if (in_array($game->$type_text, $red_array)) {
                $all_games[$key]->class = 'item-red';
                ++$total_red_count;
            } else if ($game->$type_text == 0) {
                $all_games[$key]->class = 'item-violet-red';
                ++$total_violet_count;
                ++$total_red_count;
            } else if ($game->$type_text == 5) {
                $all_games[$key]->class = 'item-violet-green';
                ++$total_violet_count;
                ++$total_green_count;
            }
            $new_array = [
                'id' => $game->id,
                'game_id' => $game->game_id,
                'code' => $game->code,
                'status' => $game->status,
                'class' => $game->class
            ];
            array_push($new_reference, $new_array);
        }

        // return $new_array;

        $colorClass = [
            "item-violet-red" => "item-violet-red",
            "item-violet-green" => "item-violet-green",
            "item-green" => "item-green",
            "item-red" => "item-red"
        ];

        $columns = [];
        $tempArray = [];
        $currentColor = null;

        foreach ($new_reference as $key => $value) {
            $color = $value["class"];

            // Initialize currentColor in the first iteration
            if ($currentColor === null) {
                $currentColor = $color;
            }

            // Group items with the same color
            if ($color === $currentColor) {
                $tempArray[] = $value;
            } else {
                // Push current group to columns and reset for the new color group
                if (!empty($tempArray)) {
                    $columns[] = $tempArray;
                }
                $tempArray = [$value];
                $currentColor = $color; // Update currentColor to the new color
            }

            // Push the last group at the end of the loop
            if ($key == count($new_reference) - 1) {
                $columns[] = $tempArray;
            }
        }


        $topMostLength = 0;
        foreach ($columns as $key => $item) {
            if ($topMostLength < count($item)) {
                $topMostLength = count($item);
            }
        }

        $columnToRow = [];
        $storeArray = [];
        $innerStoreArray = [];

        foreach ($columns as $key => $item) {
            for ($i = 0; $i < $topMostLength; $i++) {
                $current = [];
                if (isset($columnToRow[$i])) {
                    $current = $columnToRow[$i];
                }
                $value = null;
                if (isset($item[$i])) {
                    $value = $item[$i];
                }
                $columnToRow[$i] = [...$current, $value];
            }
        }


        $plainArray = [];
        foreach ($columns as $plainArrayKey => $plainArrayValue) {
            foreach ($plainArrayValue as  $plainArrayValueInner) {
                if (!in_array($plainArrayValueInner, $plainArray)) {
                    array_push($plainArray, $plainArrayValueInner);
                }
            }
        }



        $date_now = strtotime(date('Y-m-d H:i:s'));
        $last_game_time = getGameTime($last_two_games[0]->created_at, $time_interval);

        // return $columnToRow;
        // return $plainArray;

        return view('userDashboard.trend', compact('columnToRow', 'total_green_count', 'total_red_count', 'total_violet_count', 'last_two_games', 'all_games', 'type', 'last_game_time', 'date_now', 'typeText', 'plainArray'));
    }

    public function TrendRecords(Request $request)
    {
        $request->validate([
            'type' => 'required'
        ]);
        $type = $request->type;
        $green_array = [1, 3, 7, 9];
        $red_array = [2, 4, 6, 8];

        $time_interval = 1;
        if ($type == "three_minute") {
            $time_interval = 3;
        } else if ($type == "five_minute") {
            $time_interval = 5;
        } else if ($type == "two_minute") {
            $time_interval = 2;
        }

        $type_text = $type . '_code';
        $last_two_games = GameId::where(['type' => $request->type])->orderBy('id', 'desc')->limit(2)->get();
        if (in_array($last_two_games[1]->$type_text, $green_array)) {
            $last_two_games[1]->class = 'item-green';
        } else if (in_array($last_two_games[1]->$type_text, $red_array)) {
            $last_two_games[1]->class = 'item-red';
        } else if ($last_two_games[1]->$type_text == 0) {
            $last_two_games[1]->class = 'item-violet-red';
        } else if ($last_two_games[1]->$type_text == 5) {
            $last_two_games[1]->class = 'item-violet-green';
        }
        $last_two_games[1]->code = $last_two_games[1]->$type_text;

        $all_games = GameId::where(['status' => 1])
            ->whereDate('created_at', Carbon::today())
            ->select("*", "$type_text as code")
            ->where('type', $type)
            ->orderBy('id', 'desc')->get();

        $new_reference = [];

        $total_green_count = 0;
        $total_red_count = -1;
        $total_violet_count = 0;
        foreach ($all_games as $key => $game) {
            if (in_array($game->$type_text, $green_array)) {
                $all_games[$key]->class = 'item-green';
                ++$total_green_count;
            } else if (in_array($game->$type_text, $red_array)) {
                $all_games[$key]->class = 'item-red';
                ++$total_red_count;
            } else if ($game->$type_text == 0) {
                $all_games[$key]->class = 'item-violet-red';
                ++$total_violet_count;
                ++$total_red_count;
            } else if ($game->$type_text == 5) {
                $all_games[$key]->class = 'item-violet-green';
                ++$total_violet_count;
                ++$total_green_count;
            }
            $new_array = [
                'id' => $game->id,
                'game_id' => $game->game_id,
                'code' => $game->code,
                'status' => $game->status,
                'class' => $game->class
            ];
            array_push($new_reference, $new_array);
        }

        $colorClass = [
            "item-violet-red" => "item-violet-red",
            "item-violet-green" => "item-violet-green",
            "item-green" => "item-green",
            "item-red" => "item-red"
        ];

        $columns = [];
        $tempArray = [];
        $currentColor = "";

        foreach ($new_reference as $key => $value) {
            $color = $value["class"];

            // Initialize currentColor in the first iteration
            if ($currentColor === null) {
                $currentColor = $color;
            }

            // Group items with the same color
            if ($color === $currentColor) {
                $tempArray[] = $value;
            } else {
                // Push current group to columns and reset for the new color group
                if (!empty($tempArray)) {
                    $columns[] = $tempArray;
                }
                $tempArray = [$value];
                $currentColor = $color; // Update currentColor to the new color
            }

            // Push the last group at the end of the loop
            if ($key == count($new_reference) - 1) {
                $columns[] = $tempArray;
            }
        }


        $topMostLength = 0;
        foreach ($columns as $key => $item) {
            if ($topMostLength < count($item)) {
                $topMostLength = count($item);
            }
        }
        $columnToRow = [];
        foreach ($columns as $key => $item) {
            for ($i = 0; $i < $topMostLength; $i++) {
                $current = [];
                if (isset($columnToRow[$i])) {
                    $current = $columnToRow[$i];
                }
                $value = null;
                if (isset($item[$i])) {
                    $value = $item[$i];
                }
                $columnToRow[$i] = [...$current, $value];
            }
        }
        $plainArray = [];
        foreach ($columns as $plainArrayKey => $plainArrayValue) {
            foreach ($plainArrayValue as  $plainArrayValueInner) {
                if (!in_array($plainArrayValueInner, $plainArray)) {
                    array_push($plainArray, $plainArrayValueInner);
                }
            }
        }

        $date_now = strtotime(date('Y-m-d H:i:s'));
        $last_game_time = getGameTime($last_two_games[0]->created_at, $time_interval);
        return response()->json(['status' => 'success', 'columnToRow' => $columnToRow, 'total_green_count' => $total_green_count, 'total_red_count' => $total_red_count, 'total_violet_count' => $total_violet_count, 'last_two_games' => $last_two_games, 'all_games' => $all_games, 'last_game_time' => $last_game_time, 'date_now' => $date_now, 'plainArray' => $plainArray]);
    }

    public function GetGamesTime(Request $request)
    {
        $tab = $request->tab;

        $active_game = GameId::where(['status' => 0, 'type' => 'one_minute'])
            ->orderBy('id', 'desc')
            ->first();

        $two_minute_game = GameId::where(['status' => 0, 'type' => 'two_minute'])
            ->orderBy('id', 'desc')
            ->first();

        $three_minute_game = GameId::where(['status' => 0, 'type' => 'three_minute'])
            ->orderBy('id', 'desc')
            ->first();

        $five_minute_game = GameId::where(['status' => 0, 'type' => 'five_minute'])
            ->orderBy('id', 'desc')
            ->first();


        $last_game_one_minute_time = getGameTime($active_game->created_at, 1);
        $last_game_two_minute_time = getGameTime($two_minute_game->created_at, 2);
        $last_game_three_minute_time = getGameTime($three_minute_game->created_at, 3);
        $last_game_five_minute_time = getGameTime($five_minute_game->created_at, 5);

        if ($tab == 'one_minute') {
            $last_game_time = $last_game_one_minute_time;
        } else if ($tab == 'two_minute') {
            $last_game_time = $last_game_two_minute_time;
        } else if ($tab == 'three_minute') {
            $last_game_time = $last_game_three_minute_time;
        } else if ($tab == 'five_minute') {
            $last_game_time = $last_game_five_minute_time;
        }


        return response()->json([
            'status' => 'success',
            'last_game_one_minute_time' => $last_game_one_minute_time,
            'last_game_two_minute_time' => $last_game_two_minute_time,
            'last_game_three_minute_time' => $last_game_three_minute_time,
            'last_game_five_minute_time' => $last_game_five_minute_time,
            'last_game_time' => $last_game_time
        ]);
    }

    private function getGameInterval($id)
    {
        $property_name = match ($id) {
            "2minute" => 2,
            "3minute" => 3,
            "5minute" => 5,
            "1minute" => 1,
            default => 1,
        };

        return $property_name;
    }

    private function getGameInterval2($id)
    {
        $property_name = match ($id) {
            "two_minute" => 2,
            "three_minute" => 3,
            "five_minute" => 5,
            "one_minute" => 1,
            default => 1,
        };

        return $property_name;
    }

    private function getGameTypeFromInterval($type)
    {

        $property_name = match ($type) {
            1 => "one_minute",
            2 => "two_minute",
            3 => "three_minute",
            5 => "five_minute",
            default => "one_minute",
        };

        // Log::info('getGameTypeFromInterval');
        // Log::info('type: ' . $type);
        // Log::info('property_name: ' . $property_name);

        return $property_name;
    }

    private function getSingleGameTime($status, $interval)
    {
        $game_type = $this->getGameTypeFromInterval($interval);
        if ($status !== NULL)
            $game = GameId::where(['status' => $status, 'type' => $game_type])->orderBy('id', 'desc')->first();
        else $game = GameId::where(['type' => $game_type])->orderBy('id', 'desc')->first();

        // Log::info('');
        // Log::info('getSingleGameTime');
        // Log::info('status: ' . $status);
        // Log::info('interval: ' . $interval);
        // Log::info('game_type: ' . $game_type);

        $game_time = getGameTime($game->created_at, $interval);

        // $time_left = $game_time - strtotime(date('Y-m-d H:i:s'));
        // Log::info('time_left: ' . $time_left);

        return $game_time;
    }

    private function getGames($id = 1)
    {
        $game_type = $this->getGameTypeFromInterval($id);

        $games = GameId::where(['status' => 1, 'type' => $game_type])->with(['betting'])->orderBy('id', 'desc')
            ->whereDate('created_at', Carbon::today())
            ->get();
        if ($games->count() == 0) {
            $games = GameId::where(['status' => 0, 'type' => $game_type])->with(['betting'])
                ->orderBy('id', 'desc')
                ->whereDate('created_at', Carbon::today())
                ->get();

            if ($games->count() == 0) {
                $game_id = generateGameId(1, NULL);
                $gameId = new GameId();
                $gameId->game_id = $game_id;
                $gameId->type = $game_type;
                $gameId->status = 0;
                $gameId->open_price = rand(30000, 40000);
                $gameId->save();

                $games = GameId::where(['status' => 0, 'type' => $game_type])->with(['betting'])
                    ->orderBy('id', 'desc')
                    ->whereDate('created_at', Carbon::today())
                    ->get();
            }
        }

        return $games;
    }


    public function GameDashboardWithType($id = '1minute')
    {

        $game_interval = $this->getGameInterval($id);
        $type = $this->getGameTypeFromInterval($game_interval);

        $user = User::where(['id' => Auth::user()->id])->first();
        $games = $this->getGames($game_interval);

        $my_bettings = Betting::where(['user_id' => Auth::user()->id, 'tab' => $type])->with(['gameId'])
            ->orderBy('id', 'desc')
            ->get();

        $all_bettings = GameId::where(['type' => $type])->with(['betting', 'gamePoint'])
            ->orderBy('id', 'desc')
            ->whereDate('created_at', Carbon::today())
            ->get();

        $date_now = strtotime(date('Y-m-d H:i:s'));
        $last_game_time = $last_game_one_minute_time = $this->getSingleGameTime(0, 1);
        $last_game_two_minute_time = $this->getSingleGameTime(0, 2);
        $last_game_three_minute_time = $this->getSingleGameTime(0, 3);
        $last_game_five_minute_time = $this->getSingleGameTime(0, 5);

        $last_game_time = $game_interval == 1 ? $last_game_one_minute_time : ($game_interval == 2 ? $last_game_two_minute_time : ($game_interval == 3 ? $last_game_three_minute_time : $last_game_five_minute_time));


        return view('userDashboard.gameDashboard', compact(
            'user',
            'games',
            'my_bettings',
            'all_bettings',
            'date_now',
            'last_game_time',
            'type',

            'last_game_time',
            'last_game_one_minute_time',
            'last_game_two_minute_time',
            'last_game_three_minute_time',
            'last_game_five_minute_time'
        ));
    }

    public function GameRecords(Request $request)
    {

        $request->validate([
            'tab' => 'required'
        ]);

        $game_interval = $this->getGameInterval2($request->tab);
        $type = $this->getGameTypeFromInterval($game_interval);

        // Log::info('GameRecords');
        // Log::info('tab: ' . $request->tab);
        // Log::info('game_interval: ' . $game_interval);
        // Log::info('type: ' . $type);

        $all_bettings = GameId::where(['status' => 1, 'type' => $type])
            ->with(['betting'])
            ->orderBy('id', 'desc')
            ->whereDate('created_at', Carbon::today())
            ->get();
        foreach ($all_bettings as $key => $game_id) {
            $tab_code = $type . "_code";
            $all_bettings[$key]->code = $game_id->$tab_code;
            $all_bettings[$key]->gamePoint = GamePoints::where(['game_code' => $game_id->$tab_code])->first();
            if (count($game_id->betting) > 0) {
                $betting_data = findLatestBettingByType($type, $game_id->game_id);
                $all_bettings[$key]->total_amount = $betting_data['total_amount'];
                $all_bettings[$key]->count = $betting_data['count'];
            } else {
                $all_bettings[$key]->total_amount = 0;
                $all_bettings[$key]->count = 0;
            }
        }

        $active_game_id = GameId::where(['type' => $type])
            ->orderBy('id', 'desc')
            ->first();
        $user = User::where(['id' => Auth::user()->id])->first();

        $date_now = strtotime(date('Y-m-d H:i:s'));

        $last_game_one_minute_time = $this->getSingleGameTime(NULL, 1);
        $last_game_two_minute_time = $this->getSingleGameTime(NULL, 2);
        $last_game_three_minute_time = $this->getSingleGameTime(NULL, 3);
        $last_game_five_minute_time = $this->getSingleGameTime(NULL, 5);

        $last_game_time = $game_interval == 1 ? $last_game_one_minute_time : ($game_interval == 2 ? $last_game_two_minute_time : ($game_interval == 3 ? $last_game_three_minute_time : $last_game_five_minute_time));


        return response()->json([
            'status' => 'success',
            'all_bettings' => $all_bettings,
            'active_game_id' => $active_game_id,
            'user_balance' => $user->amount,
            'date_now' => $date_now,

            'last_game_time' => $last_game_time,
            'last_game_one_minute_time' => $last_game_one_minute_time,
            'last_game_two_minute_time' => $last_game_two_minute_time,
            'last_game_three_minute_time' => $last_game_three_minute_time,
            'last_game_five_minute_time' => $last_game_five_minute_time
        ]);
    }

    public function MyGameRecords(Request $request)
    {
        $request->validate([
            'tab' => 'required'
        ]);
        $my_bettings = Betting::where(['user_id' => Auth::user()->id, 'tab' => $request->tab])->with(['gameId'])
            ->orderBy('id', 'desc')
            ->get();
        return response()->json(['status' => 'success', 'my_bettings' => $my_bettings]);
    }

    public function SaveBet(Request $request)
    {
        $request->validate([
            'numbers' => 'required',
            'tab' => 'required',
            'value' => 'required',
            'game_id' => 'required'
        ]);

        $date_now = strtotime(date('Y-m-d H:i:s'));
        $time_interval = 1;
        $game_type = "one_minute";
        if ($request->tab == "three_minute") {
            $time_interval = 3;
            $game_type = "three_minute";
        } else if ($request->tab == "five_minute") {
            $time_interval = 5;
            $game_type = "five_minute";
        } else if ($request->tab == "two_minute") {
            $time_interval = 2;
            $game_type = "two_minute";
        }

        $active_game_id = GameId::where(['type' => $game_type])->orderBy('id', 'desc')->first();

        $last_game_time = getGameTime($active_game_id->created_at, $time_interval);
        $difference = $last_game_time - $date_now;
        if ($difference < 6) {
            return response()->json(['status' => 'error', 'message' => 'Bet cannot be placed. Time is over.', $time_interval, $difference, $active_game_id]);
        }

        $user = User::where(['id' => Auth::user()->id])->first();

        if ($user->amount < $request->value) {
            return response()->json(['status' => 'error', 'message' => 'Balance is not enough.']);
        }

        $user->decrement('amount', $request->value);
        $payment_settings = PaymentSettings::first();
        $amount = $request->value - ($request->value * ($payment_settings->bet_fee / 100));
        if ($user->rcode != null) {
            $this->giveCommission($user->rcode, $amount);
        }

        $numbers = $request->numbers;
        $code = null;
        if (count($numbers) == 1) {
            $type = "individual";
            $code = $numbers[0];
        } else {
            $type = "join";
            foreach ($numbers as $value) {
                $code .= $value . ",";
            }
        }

        $betting = new Betting();
        $betting->user_id = Auth::user()->id;
        $betting->game_id = $active_game_id->game_id;
        $betting->type = $type;
        $betting->code = $code;
        $betting->color = $request->color;
        $betting->value = $request->value;
        $betting->amount = $amount;
        $betting->tab = $request->tab;
        $betting->status = 0;
        $betting->save();

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

    public function giveCommission($rcode, $amount)
    {
        $user_id = Auth::user()->id;
        $payment_settings = PaymentSettings::first();
        $first_user = User::where(['owncode' => $rcode])->first();
        if ($first_user) {
            $commission_amount = ($payment_settings->level1_bet_commission / 100) * $amount;
            $commission = new Commission();
            $commission->user_id = $user_id;
            $commission->commission = $commission_amount;
            $commission->amount = $amount;
            $commission->commission_user_id = $first_user->id;
            $commission->level1 = 1;
            $commission->save();
            $first_user->increment('amount', $commission_amount);

            if ($first_user->rcode != null) {
                $second_user = User::where(['owncode' => $first_user->rcode])->first();
                if ($second_user) {
                    $commission_amount = ($payment_settings->level2_bet_commission / 100) * $amount;

                    $commission = new Commission();
                    $commission->user_id = $user_id;
                    $commission->commission = $commission_amount;
                    $commission->amount = $amount;
                    $commission->commission_user_id = $second_user->id;
                    $commission->level2 = 1;
                    $commission->save();
                    $second_user->increment('amount', $commission_amount);

                    if ($second_user->rcode != null) {
                        $third_user = User::where(['owncode' => $second_user->rcode])->first();
                        if ($third_user) {
                            $commission_amount = ($payment_settings->level3_bet_commission / 100) * $amount;

                            $commission = new Commission();
                            $commission->user_id = $user_id;
                            $commission->commission = $commission_amount;
                            $commission->amount = $amount;
                            $commission->commission_user_id = $third_user->id;
                            $commission->level3 = 1;
                            $commission->save();
                            $third_user->increment('amount', $commission_amount);
                        }
                    }
                }
            }
        }
    }
}
