<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Cashier\Services\PaymentRequestService;

class GameController extends Controller
{
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();

        $games = $db->select(
            "SELECT g.*, f.name_ar as facility_name,
                    (SELECT COUNT(*) FROM sa_game_sessions gs WHERE gs.game_id = g.id AND gs.status IN ('open','in_progress')) as active_sessions
             FROM sa_games g
             LEFT JOIN sa_facilities f ON f.id = g.facility_id
             WHERE g.is_active = 1
             ORDER BY g.name_ar"
        );

        return $this->view('SportsActivity.Views.games.index', [
            'games' => $games,
        ]);
    }

    public function create(Request $request): Response
    {
        $db = App::getInstance()->db();
        $facilities = $db->select("SELECT id, name_ar FROM sa_facilities WHERE is_archived = 0 ORDER BY name_ar");

        return $this->view('SportsActivity.Views.games.create', [
            'facilities' => $facilities,
        ]);
    }

    public function store(Request $request): Response
    {
        $db = App::getInstance()->db();

        $name = trim((string) $request->post('name_ar', ''));
        if ($name === '') {
            return $this->redirect('/sa/games/create')->withError('اسم اللعبة مطلوب');
        }

        $pricingType = in_array($request->post('pricing_type', ''), ['per_game', 'per_hour'], true)
            ? $request->post('pricing_type')
            : 'per_game';

        $db->insert('sa_games', [
            'name_ar'          => $name,
            'name_en'          => trim((string) $request->post('name_en', '')) ?: null,
            'description'      => trim((string) $request->post('description', '')) ?: null,
            'game_type'        => $request->post('game_type', 'free_play'),
            'facility_id'      => ((int) $request->post('facility_id', 0)) ?: null,
            'max_players'      => max(1, (int) $request->post('max_players', 20)),
            'duration_minutes' => max(15, (int) $request->post('duration_minutes', 60)),
            'fee_member'       => max(0, (float) $request->post('fee_member', 0)),
            'fee_nonmember'    => max(0, (float) $request->post('fee_nonmember', 0)),
            'pricing_type'     => $pricingType,
            'is_active'        => 1,
            'created_by'       => (int) (App::getInstance()->session()->get('employee_id') ?? 0),
            'created_at'       => date('Y-m-d H:i:s'),
            'updated_at'       => date('Y-m-d H:i:s'),
        ]);

        return $this->redirect('/sa/games')->withSuccess('تم إنشاء اللعبة بنجاح');
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $game = $db->selectOne("SELECT g.*, f.name_ar as facility_name FROM sa_games g LEFT JOIN sa_facilities f ON f.id = g.facility_id WHERE g.id = ?", [(int) $id]);
        if (!$game) {
            return $this->redirect('/sa/games')->withError('اللعبة غير موجودة');
        }

        $sessions = $db->select(
            "SELECT gs.*,
                    fu.name_ar as unit_name
             FROM sa_game_sessions gs
             LEFT JOIN sa_facility_units fu ON fu.id = gs.facility_unit_id
             WHERE gs.game_id = ?
             ORDER BY gs.session_date DESC, gs.start_time DESC
             LIMIT 50",
            [(int) $id]
        );

        return $this->view('SportsActivity.Views.games.show', [
            'game'     => $game,
            'sessions' => $sessions,
        ]);
    }

    public function createSession(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $game = $db->selectOne("SELECT * FROM sa_games WHERE id = ? AND is_active = 1", [(int) $id]);
        if (!$game) {
            return $this->redirect('/sa/games')->withError('اللعبة غير موجودة');
        }

        $sessionDate = trim((string) $request->post('session_date', ''));
        $startTime = trim((string) $request->post('start_time', ''));
        $endTime = trim((string) $request->post('end_time', ''));

        if (!$sessionDate || !$startTime || !$endTime) {
            return $this->redirect('/sa/games/' . $id)->withError('جميع الحقول مطلوبة');
        }

        $db->insert('sa_game_sessions', [
            'game_id'          => (int) $id,
            'session_date'     => $sessionDate,
            'start_time'       => $startTime,
            'end_time'         => $endTime,
            'facility_unit_id' => ((int) $request->post('facility_unit_id', 0)) ?: null,
            'max_players'      => (int) ($game['max_players'] ?? 20),
            'current_players'  => 0,
            'status'           => 'open',
            'notes'            => trim((string) $request->post('notes', '')) ?: null,
            'created_by'       => (int) (App::getInstance()->session()->get('employee_id') ?? 0),
            'created_at'       => date('Y-m-d H:i:s'),
            'updated_at'       => date('Y-m-d H:i:s'),
        ]);

        return $this->redirect('/sa/games/' . $id)->withSuccess('تم إنشاء الجلسة بنجاح');
    }

    public function sessionDetail(Request $request, string $id, string $sessionId): Response
    {
        $db = App::getInstance()->db();

        $game = $db->selectOne("SELECT * FROM sa_games WHERE id = ?", [(int) $id]);
        if (!$game) {
            return $this->redirect('/sa/games')->withError('اللعبة غير موجودة');
        }

        $session = $db->selectOne("SELECT * FROM sa_game_sessions WHERE id = ? AND game_id = ?", [(int) $sessionId, (int) $id]);
        if (!$session) {
            return $this->redirect('/sa/games/' . $id)->withError('الجلسة غير موجودة');
        }

        $tickets = $db->select(
            "SELECT t.*, p.full_name_ar as sa_player_name
             FROM sa_game_tickets t
             LEFT JOIN sa_players p ON p.id = t.player_id
             WHERE t.session_id = ?
             ORDER BY t.created_at ASC",
            [(int) $sessionId]
        );

        return $this->view('SportsActivity.Views.games.session', [
            'game'    => $game,
            'session' => $session,
            'tickets' => $tickets,
        ]);
    }

    public function issueTicket(Request $request, string $id, string $sessionId): Response
    {
        $db = App::getInstance()->db();

        $session = $db->selectOne("SELECT * FROM sa_game_sessions WHERE id = ? AND game_id = ?", [(int) $sessionId, (int) $id]);
        if (!$session) {
            return $this->redirect('/sa/games/' . $id)->withError('الجلسة غير موجودة');
        }

        if (!in_array($session['status'], ['open', 'in_progress'], true)) {
            return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withError('الجلسة غير متاحة للتسجيل');
        }

        if ((int) $session['current_players'] >= (int) $session['max_players']) {
            return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withError('الجلسة ممتلئة');
        }

        $game = $db->selectOne("SELECT * FROM sa_games WHERE id = ?", [(int) $id]);

        $playerIdInput = (int) $request->post('player_id', 0);
        $playerName = trim((string) $request->post('player_name', ''));
        $playerType = $request->post('player_type', 'guest');

        if (!$playerIdInput && !$playerName) {
            return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withError('يجب تحديد اللاعب أو إدخال اسم');
        }

        $baseFee = match ($playerType) {
            'member' => (float) ($game['fee_member'] ?? 0),
            default  => (float) ($game['fee_nonmember'] ?? 0),
        };

        $fee = $baseFee;
        if (($game['pricing_type'] ?? 'per_game') === 'per_hour') {
            $startDt = new \DateTime($session['session_date'] . ' ' . $session['start_time']);
            $endDt = new \DateTime($session['session_date'] . ' ' . $session['end_time']);
            $hours = max(1, (int) ceil(($endDt->getTimestamp() - $startDt->getTimestamp()) / 3600));
            $fee = $baseFee * $hours;
        }

        $ticketNumber = 'GT-' . strtoupper(substr(uniqid(), -8));

        $db->beginTransaction();
        try {
            $ticketId = $db->insert('sa_game_tickets', [
                'session_id'     => (int) $sessionId,
                'ticket_number'  => $ticketNumber,
                'player_id'      => $playerIdInput ?: null,
                'player_name'    => $playerName ?: null,
                'player_type'    => $playerType,
                'fee_charged'    => $fee,
                'payment_status' => $fee > 0 ? 'unpaid' : 'paid',
                'status'         => 'active',
                'created_by'     => (int) (App::getInstance()->session()->get('employee_id') ?? 0),
                'created_at'     => date('Y-m-d H:i:s'),
                'updated_at'     => date('Y-m-d H:i:s'),
            ]);

            if ($fee > 0) {
                $description = 'تذكرة ' . ($game['name_ar'] ?? 'لعبة') . ' — ' . ($playerName ?: 'لاعب');
                $payResult = PaymentRequestService::createRequest([
                    'member_id'           => 0,
                    'payment_type'        => 'sa_game_ticket',
                    'amount'              => (string) $fee,
                    'description_ar'      => $description,
                    'related_entity_type' => 'sa_game_tickets',
                    'related_entity_id'   => $ticketId,
                ]);

                if ($payResult['success']) {
                    $db->update('sa_game_tickets', [
                        'payment_id' => (int) $payResult['request_id'],
                        'updated_at' => date('Y-m-d H:i:s'),
                    ], 'id = ?', [$ticketId]);
                }
            }

            $db->update('sa_game_sessions', [
                'current_players' => (int) $session['current_players'] + 1,
                'updated_at'      => date('Y-m-d H:i:s'),
            ], 'id = ?', [(int) $sessionId]);

            $newCount = (int) $session['current_players'] + 1;
            if ($newCount >= (int) $session['max_players']) {
                $db->update('sa_game_sessions', ['status' => 'full'], 'id = ?', [(int) $sessionId]);
            }

            $db->commit();
        } catch (\Throwable $e) {
            $db->rollBack();
            return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withError('فشل إصدار التذكرة: ' . $e->getMessage());
        }

        $msg = "تم إصدار تذكرة {$ticketNumber} بنجاح";
        if ($fee > 0) {
            $msg .= ' — في انتظار التحصيل من الخزنة';
        }
        return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withSuccess($msg);
    }

    public function startSession(Request $request, string $id, string $sessionId): Response
    {
        $db = App::getInstance()->db();

        $session = $db->selectOne("SELECT * FROM sa_game_sessions WHERE id = ? AND game_id = ?", [(int) $sessionId, (int) $id]);
        if (!$session) {
            return $this->redirect('/sa/games/' . $id)->withError('الجلسة غير موجودة');
        }

        if ($session['status'] !== 'open') {
            return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withError('لا يمكن بدء الجلسة — الحالة الحالية: ' . $session['status']);
        }

        $db->update('sa_game_sessions', [
            'status'     => 'in_progress',
            'updated_at' => date('Y-m-d H:i:s'),
        ], 'id = ?', [(int) $sessionId]);

        return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withSuccess('تم بدء الجلسة');
    }

    public function completeSession(Request $request, string $id, string $sessionId): Response
    {
        $db = App::getInstance()->db();

        $session = $db->selectOne("SELECT * FROM sa_game_sessions WHERE id = ? AND game_id = ?", [(int) $sessionId, (int) $id]);
        if (!$session) {
            return $this->redirect('/sa/games/' . $id)->withError('الجلسة غير موجودة');
        }

        if (!in_array($session['status'], ['open', 'in_progress', 'full'], true)) {
            return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withError('لا يمكن إنهاء الجلسة');
        }

        $db->update('sa_game_sessions', [
            'status'     => 'completed',
            'updated_at' => date('Y-m-d H:i:s'),
        ], 'id = ?', [(int) $sessionId]);

        return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withSuccess('تم إنهاء الجلسة');
    }

    public function cancelSession(Request $request, string $id, string $sessionId): Response
    {
        $db = App::getInstance()->db();

        $session = $db->selectOne("SELECT * FROM sa_game_sessions WHERE id = ? AND game_id = ?", [(int) $sessionId, (int) $id]);
        if (!$session) {
            return $this->redirect('/sa/games/' . $id)->withError('الجلسة غير موجودة');
        }

        if ($session['status'] === 'completed') {
            return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withError('لا يمكن إلغاء جلسة مكتملة');
        }

        $db->update('sa_game_sessions', [
            'status'     => 'cancelled',
            'updated_at' => date('Y-m-d H:i:s'),
        ], 'id = ?', [(int) $sessionId]);

        return $this->redirect("/sa/games/{$id}/sessions/{$sessionId}")->withSuccess('تم إلغاء الجلسة');
    }
}
