<?php

namespace App\Http\Controllers\Api;

use App\Events\TarneebUpdated;
use App\Http\Controllers\Controller;
use App\Models\TarneebGame;
use App\Models\WalletTransaction;
use App\Services\TarneebEngine;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class TarneebGameController extends Controller
{
    protected const JOIN_TIMEOUT_MINUTES = 20;

    // ==============================================================
    // إنشاء لعبة جديدة
    // ==============================================================

    public function store(Request $request)
    {
        $data = $request->validate([
            'bet_amount_per_player' => 'required|numeric|min:100',
        ]);

        $user = $request->user();
        $amount = (float) $data['bet_amount_per_player'];

        if ($user->wallet->balance < $amount) {
            return response()->json(['message' => 'رصيدك غير كافٍ لهذا الرهان'], 400);
        }

        $game = DB::transaction(function () use ($user, $amount) {
            $user->wallet()->decrement('balance', $amount);

            WalletTransaction::create([
                'transaction_id' => (string) Str::uuid(),
                'user_id' => $user->id,
                'type' => 'game_bet',
                'amount' => $amount,
                'status' => 'completed',
            ]);

            return TarneebGame::create([
                'seat0_user_id' => $user->id,
                'bet_amount_per_player' => $amount,
                'commission_percent' => \App\Models\PlatformSetting::get('commission_percent', 10),
                'status' => 'waiting',
                'expires_at' => now()->addMinutes(self::JOIN_TIMEOUT_MINUTES),
                'scores' => ['0' => 0, '1' => 0, '2' => 0, '3' => 0],
            ]);
        });

        return response()->json([
            'game' => $this->formatGame($game, $user->id),
            'invite_url' => config('app.frontend_url') . '/games/tarneeb/' . $game->uuid,
        ], 201);
    }

    // ==============================================================
    // عرض الحالة (مخصّصة لكل لاعب — أوراقه هو بس)
    // ==============================================================

    public function show(Request $request, string $uuid)
    {
        $game = TarneebGame::with(['seat0', 'seat1', 'seat2', 'seat3'])->where('uuid', $uuid)->firstOrFail();
        return response()->json($this->formatGame($game, $request->user()?->id));
    }

    // ==============================================================
    // الانضمام — أول واحد ينضم = شريك المُنشئ (فريق A)، والاثنين بعده فريق B
    // ==============================================================

    public function join(Request $request, string $uuid)
    {
        $user = $request->user();

        $game = DB::transaction(function () use ($user, $uuid) {
            $game = TarneebGame::where('uuid', $uuid)->lockForUpdate()->firstOrFail();

            if ($game->status !== 'waiting') {
                abort(400, 'هذه اللعبة لم تعد متاحة للانضمام');
            }
            if (in_array($user->id, array_filter($game->seatUserIds()), true)) {
                abort(400, 'أنت منضم أصلاً لهذه اللعبة');
            }
            if ($game->expires_at && $game->expires_at->isPast()) {
                abort(400, 'انتهت مهلة الانضمام لهذه اللعبة');
            }
            if ($user->wallet->balance < $game->bet_amount_per_player) {
                abort(400, 'رصيدك غير كافٍ للانضمام لهذا الرهان');
            }

            // أول مقعد فاضي بالترتيب: 2 (شريك المنشئ) ثم 1 ثم 3
            $nextSeat = match (true) {
                $game->seat2_user_id === null => 2,
                $game->seat1_user_id === null => 1,
                $game->seat3_user_id === null => 3,
                default => abort(400, 'اللعبة مكتملة بالفعل'),
            };

            $user->wallet()->decrement('balance', $game->bet_amount_per_player);

            WalletTransaction::create([
                'transaction_id' => (string) Str::uuid(),
                'user_id' => $user->id,
                'type' => 'game_bet',
                'amount' => $game->bet_amount_per_player,
                'status' => 'completed',
            ]);

            $game->update(["seat{$nextSeat}_user_id" => $user->id]);
            $game->refresh();

            if ($game->isFull()) {
                $this->startNewHand($game);
                $game->update(['status' => 'in_progress', 'expires_at' => null]);
            }

            return $game->fresh(['seat0', 'seat1', 'seat2', 'seat3']);
        });

        broadcast(new TarneebUpdated($game->uuid))->toOthers();

        return response()->json($this->formatGame($game, $user->id));
    }

    // ==============================================================
    // إرسال رقم الضمن
    // ==============================================================

    public function submitBid(Request $request, string $uuid)
    {
        $data = $request->validate([
            'bid' => 'required|integer|min:2|max:13',
        ]);

        $user = $request->user();

        DB::transaction(function () use ($user, $uuid, $data) {
            $game = TarneebGame::where('uuid', $uuid)->lockForUpdate()->firstOrFail();

            $seat = $game->seatOf($user->id);
            if ($seat === null) {
                abort(403, 'أنت لست طرفاً بهذه اللعبة');
            }
            if ($game->phase !== 'bidding') {
                abort(400, 'مرحلة المزايدة انتهت');
            }
            if ($game->current_turn_seat !== $seat) {
                abort(400, 'مو دورك بالمزايدة');
            }

            $minBid = TarneebEngine::minimumAllowedBid((int) $game->scores[(string) $seat]);
            if ($data['bid'] < $minBid) {
                abort(400, "أقل ضمن مسموح لك حالياً هو {$minBid} (بسبب نقاطك الحالية)");
            }

            $bids = $game->bids ?? ['0' => null, '1' => null, '2' => null, '3' => null];
            $bids[(string) $seat] = $data['bid'];
            $game->bids = $bids;

            $allBidsIn = collect($bids)->every(fn ($b) => $b !== null);

            if (!$allBidsIn) {
                $game->current_turn_seat = ($seat + 1) % 4;
                $game->save();
                return;
            }

            // ✅ الأربعة ضمنوا — نتحقق من المجموع (13 أو أكثر = طبيعي ويُلعب،
            // أقل من 13 فقط هو اللي يستوجب إعادة التوزيع)
            $sum = array_sum($bids);

            if ($sum < 13) {
                // ❌ المجموع أقل من 13 — إعادة توزيع كاملة (نفس الموزّع)
                $game->redeal_count += 1;
                $game->save();
                $this->startNewHand($game->fresh());
                return;
            }

            // ✅ صحّت المزايدة — نبلش مرحلة اللعب
            $game->phase = 'playing';
            $game->current_trick = ['leader_seat' => null, 'cards' => []];
            $firstLeader = ($game->dealer_seat + 1) % 4;
            $game->current_trick_leader_seat = $firstLeader;
            $game->current_turn_seat = $firstLeader;
            $game->lead_suit = null;
            $game->tricks_won_this_hand = ['0' => 0, '1' => 0, '2' => 0, '3' => 0];
            $game->save();
        });

        broadcast(new TarneebUpdated($uuid));

        $game = TarneebGame::with(['seat0', 'seat1', 'seat2', 'seat3'])->where('uuid', $uuid)->first();
        return response()->json($this->formatGame($game, $user->id));
    }

    // ==============================================================
    // لعب ورقة
    // ==============================================================

    public function playCard(Request $request, string $uuid)
    {
        $data = $request->validate([
            'card' => 'required|string',
        ]);

        $user = $request->user();
        $handFinished = false;
        $matchFinished = false;

        DB::transaction(function () use ($user, $uuid, $data, &$handFinished, &$matchFinished) {
            $game = TarneebGame::where('uuid', $uuid)->lockForUpdate()->firstOrFail();

            $seat = $game->seatOf($user->id);
            if ($seat === null) {
                abort(403, 'أنت لست طرفاً بهذه اللعبة');
            }
            if ($game->phase !== 'playing') {
                abort(400, 'مو وقت اللعب حالياً');
            }
            if ($game->current_turn_seat !== $seat) {
                abort(400, 'مو دورك تلعب');
            }

            $hands = $game->hands;
            $playerHand = $hands[(string) $seat] ?? [];

            if (!TarneebEngine::isValidPlay($playerHand, $data['card'], $game->lead_suit)) {
                abort(400, 'حركة غير قانونية — لازم تتبع نوع الورقة القائدة لو معك منها');
            }

            // إزالة الورقة من يد اللاعب
            $hands[(string) $seat] = array_values(array_diff($playerHand, [$data['card']]));
            $game->hands = $hands;

            $trick = $game->current_trick;
            $trick['cards'][(string) $seat] = $data['card'];

            if ($game->lead_suit === null) {
                $game->lead_suit = TarneebEngine::suitOf($data['card']);
                $trick['leader_seat'] = $seat;
            }

            $game->current_trick = $trick;

            if (count($trick['cards']) < 4) {
                // اللطشة لسا ما اكتملت — الدور يروح للمقعد التالي
                $game->current_turn_seat = ($seat + 1) % 4;
                $game->save();
                return;
            }

            // ✅ اكتملت اللطشة (4 أوراق) — نحدد الفائز
            $winnerSeat = TarneebEngine::resolveTrick($trick['cards'], $game->lead_suit, $game->trump_suit);

            $tricksWon = $game->tricks_won_this_hand;
            $tricksWon[(string) $winnerSeat] = ($tricksWon[(string) $winnerSeat] ?? 0) + 1;
            $game->tricks_won_this_hand = $tricksWon;

            // تجهيز اللطشة الجاية
            $game->current_trick = ['leader_seat' => $winnerSeat, 'cards' => []];
            $game->current_trick_leader_seat = $winnerSeat;
            $game->current_turn_seat = $winnerSeat;
            $game->lead_suit = null;

            $handOver = empty($hands[(string) $winnerSeat]) && array_sum(array_map('count', $hands)) === 0;

            if (!$handOver) {
                $game->save();
                return;
            }

            // ✅ انتهت التوزيعة بالكامل (13 لطشة) — نحسب النقاط
            $handFinished = true;
            $matchFinished = $this->finishHand($game);
        });

        broadcast(new TarneebUpdated($uuid));

        $game = TarneebGame::with(['seat0', 'seat1', 'seat2', 'seat3'])->where('uuid', $uuid)->first();
        return response()->json($this->formatGame($game, $user->id));
    }

    // ==============================================================
    // دوال داخلية
    // ==============================================================

    /**
     * توزيعة جديدة: خلط، توزيع 13 لكل مقعد، تحديد الطرنيب، بداية مرحلة المزايدة.
     */
    protected function startNewHand(TarneebGame $game): void
    {
        $dealt = TarneebEngine::dealHand($game->dealer_seat);

        $game->hands = $dealt['hands'];
        $game->trump_suit = $dealt['trump_suit'];
        $game->cut_card = $dealt['cut_card'];
        $game->bids = ['0' => null, '1' => null, '2' => null, '3' => null];
        $game->phase = 'bidding';
        $game->current_turn_seat = ($game->dealer_seat + 1) % 4;
        $game->current_trick = null;
        $game->current_trick_leader_seat = null;
        $game->lead_suit = null;
        $game->tricks_won_this_hand = ['0' => 0, '1' => 0, '2' => 0, '3' => 0];
        $game->save();
    }

    /**
     * حساب نقاط التوزيعة المكتملة، تحديث النقاط التراكمية، فحص شرط الفوز،
     * وإما تجهيز توزيعة جديدة أو إنهاء الماتش وتوزيع الأرباح.
     *
     * :return: true لو الماتش انتهى فعلياً
     */
    protected function finishHand(TarneebGame $game): bool
    {
        $bids = $game->bids;
        $tricksWon = $game->tricks_won_this_hand;
        $scores = $game->scores;
        $handScores = ['0' => 0, '1' => 0, '2' => 0, '3' => 0];

        foreach ([0, 1, 2, 3] as $seat) {
            $bid = (int) $bids[(string) $seat];
            $won = (int) ($tricksWon[(string) $seat] ?? 0);
            $value = TarneebEngine::bidScoreValue($bid);

            $delta = $won >= $bid ? $value : -$value;
            $handScores[(string) $seat] = $delta;
            $scores[(string) $seat] = (int) $scores[(string) $seat] + $delta;
        }

        $game->scores = $scores;

        \App\Models\TarneebHandHistory::create([
            'game_id' => $game->id,
            'hand_number' => $game->hand_number,
            'trump_suit' => $game->trump_suit,
            'bids' => $bids,
            'tricks_won' => $tricksWon,
            'hand_scores' => $handScores,
        ]);

        // ------------------------------------------------------------
        // فحص شرط الفوز: لاعب وصل للهدف (افتراضياً 41، قابل للتغيير من .env
        // بمتغير TARNEEB_WINNING_SCORE — مفيد للاختبار السريع) وشريكه فوق الصفر
        // ------------------------------------------------------------
        $winningScore = config('services.tarneeb.winning_score', 41);
        $winningTeam = null;
        foreach (['A' => [0, 2], 'B' => [1, 3]] as $team => $seats) {
            [$s1, $s2] = $seats;
            $score1 = (int) $scores[(string) $s1];
            $score2 = (int) $scores[(string) $s2];

            if ($score1 >= $winningScore && $score2 >= 0) {
                $winningTeam = $team;
                break;
            }
            if ($score2 >= $winningScore && $score1 >= 0) {
                $winningTeam = $team;
                break;
            }
        }

        if ($winningTeam !== null) {
            $this->finalizeMatch($game, $winningTeam);
            return true;
        }

        // الماتش مستمر — توزيعة جديدة، الموزّع ينتقل للمقعد التالي
        $game->dealer_seat = ($game->dealer_seat + 1) % 4;
        $game->hand_number += 1;
        $game->redeal_count = 0;
        $game->save();

        $this->startNewHand($game->fresh());

        return false;
    }

    /**
     * توزيع الأرباح على الفريق الفائز (نص لكل شريك) وإنهاء اللعبة.
     */
    protected function finalizeMatch(TarneebGame $game, string $winningTeam): void
    {
        $pot = $game->potAmount();
        $commission = round($pot * ((float) $game->commission_percent / 100), 2);
        $payoutTotal = $pot - $commission;
        $payoutEach = round($payoutTotal / 2, 2);

        $winnerSeats = $winningTeam === 'A' ? [0, 2] : [1, 3];
        $seatUserIds = $game->seatUserIds();

        foreach ($winnerSeats as $seat) {
            $winnerUser = \App\Models\User::find($seatUserIds[$seat]);
            $winnerUser->wallet()->increment('balance', $payoutEach);

            WalletTransaction::create([
                'transaction_id' => (string) Str::uuid(),
                'user_id' => $winnerUser->id,
                'type' => 'game_win',
                'amount' => $payoutEach,
                'status' => 'completed',
            ]);
        }

        $game->status = 'completed';
        $game->winner_team = $winningTeam;
        $game->commission_amount = $commission;
        $game->payout_per_winner = $payoutEach;
        $game->phase = 'hand_complete';
        $game->save();
    }

    protected function formatGame(TarneebGame $game, ?int $viewerId): array
    {
        $viewerSeat = $viewerId ? $game->seatOf($viewerId) : null;

        $players = [];
        foreach ([0, 1, 2, 3] as $seat) {
            $relation = $game->{"seat{$seat}"};
            $players[$seat] = $relation ? [
                'id' => $relation->id,
                'username' => $relation->username,
                'team' => $game->teamOf($seat),
            ] : null;
        }

        return [
            'uuid' => $game->uuid,
            'status' => $game->status,
            'phase' => $game->phase,
            'bet_amount_per_player' => (float) $game->bet_amount_per_player,
            'pot_amount' => $game->potAmount(),
            'commission_percent' => (float) $game->commission_percent,
            'players' => $players,
            'viewer_seat' => $viewerSeat,
            'dealer_seat' => $game->dealer_seat,
            'hand_number' => $game->hand_number,
            'trump_suit' => $game->trump_suit,
            'cut_card' => $game->cut_card,
            'bids' => $game->bids,
            'redeal_count' => $game->redeal_count,
            'current_turn_seat' => $game->current_turn_seat,
            'current_trick' => $game->current_trick,
            'lead_suit' => $game->lead_suit,
            'tricks_won_this_hand' => $game->tricks_won_this_hand,
            'scores' => $game->scores,
            'winner_team' => $game->winner_team,
            'payout_per_winner' => $game->payout_per_winner !== null ? (float) $game->payout_per_winner : null,
            // ⚠️ أوراق اللاعب صاحب الطلب فقط — باقي الأوراق ما بتنكشف إطلاقاً
            'my_hand' => $viewerSeat !== null ? ($game->hands[(string) $viewerSeat] ?? []) : [],
            'my_minimum_bid' => $viewerSeat !== null
                ? TarneebEngine::minimumAllowedBid((int) ($game->scores[(string) $viewerSeat] ?? 0))
                : null,
            'my_maximum_bid' => $viewerSeat !== null ? 13 : null,
        ];
    }
}
