<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Services;

use App\Core\App;

final class GateAccessService
{
    public static function checkAccess(string $scannedData): array
    {
        $db = App::getInstance()->db();

        $cardNumber = self::extractCardNumber($scannedData);
        if ($cardNumber === null) {
            return ['granted' => false, 'reason' => 'بيانات المسح غير صالحة'];
        }

        $card = $db->selectOne(
            "SELECT c.*, p.full_name_ar, p.photo_path, p.player_type
             FROM sa_player_cards c
             INNER JOIN sa_players p ON p.id = c.player_id
             WHERE c.card_number = ? AND c.is_archived = 0",
            [$cardNumber]
        );

        if (!$card) {
            return ['granted' => false, 'reason' => 'الكارت غير موجود في النظام'];
        }

        if ($card['status'] === 'suspended') {
            return [
                'granted' => false,
                'reason'  => 'الكارت موقوف',
                'card'    => $card,
            ];
        }

        if ($card['status'] === 'revoked') {
            return [
                'granted' => false,
                'reason'  => 'الكارت ملغى',
                'card'    => $card,
            ];
        }

        if ($card['status'] === 'expired') {
            return [
                'granted' => false,
                'reason'  => 'الكارت منتهي الصلاحية',
                'card'    => $card,
            ];
        }

        if ($card['valid_until'] !== null && $card['valid_until'] < date('Y-m-d')) {
            $db->update('sa_player_cards', [
                'status'     => 'expired',
                'updated_at' => date('Y-m-d H:i:s'),
            ], 'id = ?', [(int) $card['id']]);

            return [
                'granted' => false,
                'reason'  => 'الكارت منتهي الصلاحية',
                'card'    => $card,
            ];
        }

        if (!in_array($card['status'], ['active', 'temporary'], true)) {
            return [
                'granted' => false,
                'reason'  => 'حالة الكارت غير صالحة للدخول (' . $card['status'] . ')',
                'card'    => $card,
            ];
        }

        return [
            'granted'     => true,
            'card'        => $card,
            'player_name' => $card['full_name_ar'],
            'player_type' => $card['player_type'],
            'card_type'   => $card['card_type'],
            'valid_until' => $card['valid_until'],
        ];
    }

    public static function recordEntry(int $playerId, ?int $cardId, string $accessPoint = ''): int
    {
        $db = App::getInstance()->db();
        $employee = App::getInstance()->currentEmployee();

        return $db->insert('sa_gate_access_log', [
            'player_id'    => $playerId,
            'card_id'      => $cardId,
            'access_type'  => 'entry',
            'access_point' => $accessPoint ?: null,
            'granted'      => 1,
            'recorded_by'  => $employee ? (int) $employee->id : null,
            'recorded_at'  => date('Y-m-d H:i:s'),
        ]);
    }

    public static function recordDenial(int $playerId, ?int $cardId, string $reason, string $scannedData = ''): int
    {
        $db = App::getInstance()->db();
        $employee = App::getInstance()->currentEmployee();

        return $db->insert('sa_gate_access_log', [
            'player_id'     => $playerId,
            'card_id'       => $cardId,
            'access_type'   => 'entry',
            'access_point'  => null,
            'granted'       => 0,
            'denial_reason' => $reason,
            'scanned_data'  => $scannedData ?: null,
            'recorded_by'   => $employee ? (int) $employee->id : null,
            'recorded_at'   => date('Y-m-d H:i:s'),
        ]);
    }

    public static function recordExit(int $playerId, string $accessPoint = ''): void
    {
        $db = App::getInstance()->db();
        $employee = App::getInstance()->currentEmployee();

        $db->insert('sa_gate_access_log', [
            'player_id'    => $playerId,
            'card_id'      => null,
            'access_type'  => 'exit',
            'access_point' => $accessPoint ?: null,
            'granted'      => 1,
            'recorded_by'  => $employee ? (int) $employee->id : null,
            'recorded_at'  => date('Y-m-d H:i:s'),
        ]);
    }

    public static function getPlayerAccessHistory(int $playerId, ?string $from = null, ?string $to = null): array
    {
        $db = App::getInstance()->db();
        $where = 'g.player_id = ?';
        $params = [$playerId];

        if ($from) {
            $where .= ' AND g.recorded_at >= ?';
            $params[] = $from . ' 00:00:00';
        }
        if ($to) {
            $where .= ' AND g.recorded_at <= ?';
            $params[] = $to . ' 23:59:59';
        }

        return $db->select(
            "SELECT g.*, e.full_name_ar as recorded_by_name
             FROM sa_gate_access_log g
             LEFT JOIN employees e ON e.id = g.recorded_by
             WHERE {$where}
             ORDER BY g.recorded_at DESC
             LIMIT 200",
            $params
        );
    }

    public static function getDailyAccessReport(?string $date = null): array
    {
        $db = App::getInstance()->db();
        $date = $date ?: date('Y-m-d');

        $summary = $db->selectOne(
            "SELECT
                COUNT(*) as total_scans,
                SUM(CASE WHEN granted = 1 AND access_type = 'entry' THEN 1 ELSE 0 END) as entries_granted,
                SUM(CASE WHEN granted = 0 THEN 1 ELSE 0 END) as entries_denied,
                SUM(CASE WHEN access_type = 'exit' THEN 1 ELSE 0 END) as exits,
                COUNT(DISTINCT player_id) as unique_players
             FROM sa_gate_access_log
             WHERE DATE(recorded_at) = ?",
            [$date]
        );

        $entries = $db->select(
            "SELECT g.*, p.full_name_ar, p.player_type, c.card_number, c.card_type
             FROM sa_gate_access_log g
             INNER JOIN sa_players p ON p.id = g.player_id
             LEFT JOIN sa_player_cards c ON c.id = g.card_id
             WHERE DATE(g.recorded_at) = ?
             ORDER BY g.recorded_at DESC
             LIMIT 500",
            [$date]
        );

        return [
            'date'    => $date,
            'summary' => $summary,
            'entries' => $entries,
        ];
    }

    private static function extractCardNumber(?string $scannedData): ?string
    {
        if ($scannedData === null || $scannedData === '') {
            return null;
        }

        if (str_starts_with($scannedData, 'THECLUB:SA:')) {
            $parts = explode(':', $scannedData);
            return $parts[2] ?? null;
        }

        if (preg_match('/^SAC-\d{4}-\d{6}$/', $scannedData)) {
            return $scannedData;
        }

        return null;
    }
}
