<?php

namespace App\Http\Controllers\Api;

use App\Events\GameCancelled;
use App\Events\GameFinished;
use App\Events\GameJoined;
use App\Events\RoundResolved;
use App\Http\Controllers\Controller;
use App\Models\Game;
use App\Models\GameRound;
use App\Models\WalletTransaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;

class GameController extends Controller
{
    protected const VALID_CHOICES = ['rock', 'paper', 'scissors'];
    protected const JOIN_TIMEOUT_MINUTES = 15;

    /**
     * POST /api/games/rps
     * إنشاء لعبة جديدة — يخصم الرهان من المُنشئ فوراً (escrow).
     */
    public function store(Request $request)
    {
        $data = $request->validate([
            'bet_amount' => 'required|numeric|min:100',
        ]);

        $user = $request->user();
        $betAmount = (float) $data['bet_amount'];

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

        $game = DB::transaction(function () use ($user, $betAmount) {
            // خصم الرهان فوراً (escrow) — نفس منطق أي عملية سحب من محفظة المستخدم
            $user->wallet()->decrement('balance', $betAmount);

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

            return Game::create([
                'type' => 'rps',
                'creator_id' => $user->id,
                'bet_amount' => $betAmount,
                'commission_percent' => \App\Models\PlatformSetting::get('commission_percent', 10),
                'status' => 'waiting',
                'expires_at' => now()->addMinutes(self::JOIN_TIMEOUT_MINUTES),
            ]);
        });

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

    /**
     * GET /api/games/rps/{uuid}
     * جلب حالة اللعبة الحالية (للطرفين، ولمن يفتح رابط الدعوة).
     */
    public function show(Request $request, string $uuid)
    {
        $game = Game::with(['creator', 'opponent', 'winner'])->where('uuid', $uuid)->firstOrFail();

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

    /**
     * POST /api/games/rps/{uuid}/join
     * انضمام اللاعب الثاني — يخصم رهانه فوراً وتبدأ اللعبة.
     */
    public function join(Request $request, string $uuid)
    {
        $user = $request->user();

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

            if ($game->status !== 'waiting') {
                abort(400, 'هذه اللعبة لم تعد متاحة للانضمام');
            }

            if ($game->creator_id === $user->id) {
                abort(400, 'لا يمكنك الانضمام إلى لعبتك الخاصة');
            }

            if ($game->expires_at && $game->expires_at->isPast()) {
                abort(400, 'انتهت مهلة الانضمام لهذه اللعبة');
            }

            if ($user->wallet->balance < $game->bet_amount) {
                abort(400, 'رصيدك غير كافٍ للانضمام لهذا الرهان');
            }

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

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

            $game->update([
                'opponent_id' => $user->id,
                'status' => 'in_progress',
                'expires_at' => null,
            ]);

            return $game->fresh(['creator', 'opponent']);
        });

        broadcast(new GameJoined($game))->toOthers();

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

    /**
     * POST /api/games/rps/{uuid}/choice
     * إرسال اختيار اللاعب لهذه الجولة (حجر/ورقة/مقص).
     */
    public function submitChoice(Request $request, string $uuid)
    {
        $data = $request->validate([
            'choice' => ['required', Rule::in(self::VALID_CHOICES)],
        ]);

        $user = $request->user();

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

            if ($game->status !== 'in_progress') {
                abort(400, 'اللعبة غير نشطة حالياً');
            }

            $isCreator = $game->creator_id === $user->id;
            $isOpponent = $game->opponent_id === $user->id;

            if (!$isCreator && !$isOpponent) {
                abort(403, 'أنت لست طرفاً بهذه اللعبة');
            }

            // تسجيل اختيار هذا اللاعب لهذه الجولة
            if ($isCreator) {
                if ($game->pending_creator_choice) {
                    abort(400, 'لقد أرسلت اختيارك بالفعل لهذه الجولة');
                }
                $game->pending_creator_choice = $data['choice'];
            } else {
                if ($game->pending_opponent_choice) {
                    abort(400, 'لقد أرسلت اختيارك بالفعل لهذه الجولة');
                }
                $game->pending_opponent_choice = $data['choice'];
            }
            $game->save();

            // لو الطرف التاني لسا ما اختار، نوقف هون وننتظره
            if (!$game->pending_creator_choice || !$game->pending_opponent_choice) {
                return ['game' => $game, 'round_resolved' => false];
            }

            // ✅ كلا الطرفين اختارا — نحسم الجولة
            $creatorChoice = $game->pending_creator_choice;
            $opponentChoice = $game->pending_opponent_choice;
            $roundResult = Game::resolveRoundWinner($creatorChoice, $opponentChoice);

            if ($roundResult === 'draw') {
                // تعادل — نصفّر ونعيد نفس رقم الجولة بدون ما نسجلها كحاسمة
                $game->update([
                    'pending_creator_choice' => null,
                    'pending_opponent_choice' => null,
                ]);

                return [
                    'game' => $game,
                    'round_resolved' => true,
                    'creator_choice' => $creatorChoice,
                    'opponent_choice' => $opponentChoice,
                    'result' => 'draw',
                ];
            }

            // جولة حاسمة — نسجلها ونحدّث عداد الفوز
            $roundWinnerId = $roundResult === 'creator' ? $game->creator_id : $game->opponent_id;

            GameRound::create([
                'game_id' => $game->id,
                'round_number' => $game->round_number,
                'creator_choice' => $creatorChoice,
                'opponent_choice' => $opponentChoice,
                'round_winner_id' => $roundWinnerId,
            ]);

            $game->pending_creator_choice = null;
            $game->pending_opponent_choice = null;
            $game->round_number += 1;

            if ($roundResult === 'creator') {
                $game->creator_wins += 1;
            } else {
                $game->opponent_wins += 1;
            }

            $matchFinished = $game->hasMatchWinner();

            if ($matchFinished) {
                $game->status = 'completed';
                $game->winner_id = $roundWinnerId;

                $pot = $game->potAmount();
                $commission = round($pot * ((float) $game->commission_percent / 100), 2);
                $payout = $pot - $commission;

                $game->commission_amount = $commission;
                $game->payout_amount = $payout;

                $winnerUser = $roundResult === 'creator' ? $game->creator : $game->opponent;
                $winnerUser->wallet()->increment('balance', $payout);

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

            $game->save();

            return [
                'game' => $game,
                'round_resolved' => true,
                'creator_choice' => $creatorChoice,
                'opponent_choice' => $opponentChoice,
                'result' => $roundResult,
                'match_finished' => $matchFinished,
            ];
        });

        $game = $result['game']->fresh(['creator', 'opponent', 'winner']);

        if ($result['round_resolved']) {
            broadcast(new RoundResolved(
                $game,
                $result['creator_choice'],
                $result['opponent_choice'],
                $result['result'],
            ));

            if (!empty($result['match_finished'])) {
                broadcast(new GameFinished($game));
            }
        }

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

    /**
     * POST /api/games/rps/{uuid}/cancel
     * إلغاء لعبة لسا بانتظار خصم (المُنشئ فقط، قبل ما ينضم حدا).
     */
    public function cancel(Request $request, string $uuid)
    {
        $user = $request->user();

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

            if ($game->creator_id !== $user->id) {
                abort(403, 'غير مصرح لك بإلغاء هذه اللعبة');
            }

            if ($game->status !== 'waiting') {
                abort(400, 'لا يمكن إلغاء لعبة بدأت بالفعل');
            }

            $this->refundAndCancel($game);

            return $game->fresh();
        });

        broadcast(new GameCancelled($game, 'cancelled_by_creator'));

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

    /**
     * يُستخدم من scheduler (routes/console.php) لإلغاء الألعاب المنتهية المهلة تلقائياً.
     */
    public function refundAndCancel(Game $game): void
    {
        $game->creator->wallet()->increment('balance', $game->bet_amount);

        WalletTransaction::create([
            'transaction_id' => (string) \Illuminate\Support\Str::uuid(),
            'user_id' => $game->creator_id,
            'type' => 'game_refund',
            'amount' => $game->bet_amount,
            'status' => 'completed',
        ]);

        $game->update(['status' => 'cancelled']);
    }

    protected function formatGame(Game $game, ?int $viewerId): array
    {
        return [
            'uuid' => $game->uuid,
            'status' => $game->status,
            'bet_amount' => (float) $game->bet_amount,
            'pot_amount' => $game->potAmount(),
            'commission_percent' => (float) $game->commission_percent,
            'round_number' => $game->round_number,
            'creator_wins' => $game->creator_wins,
            'opponent_wins' => $game->opponent_wins,
            'creator' => $game->creator ? [
                'id' => $game->creator->id,
                'username' => $game->creator->username,
            ] : null,
            'opponent' => $game->opponent ? [
                'id' => $game->opponent->id,
                'username' => $game->opponent->username,
            ] : null,
            'winner_id' => $game->winner_id,
            'payout_amount' => $game->payout_amount !== null ? (float) $game->payout_amount : null,
            'is_creator' => $viewerId !== null && $game->creator_id === $viewerId,
            'is_opponent' => $viewerId !== null && $game->opponent_id === $viewerId,
            // هل أنا بانتظار خصم اللاعب التاني بالجولة الحالية؟ (للواجهة، عشان تعطل الأزرار)
            'my_choice_submitted' => $viewerId !== null && (
                ($game->creator_id === $viewerId && $game->pending_creator_choice !== null) ||
                ($game->opponent_id === $viewerId && $game->pending_opponent_choice !== null)
            ),
        ];
    }
}
