<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Services;

use App\Core\App;
use App\Core\EventBus;
use App\Modules\SportsActivity\SaConstants;

final class MakeupSessionService
{
    public static function createFromAbsence(int $playerId, int $groupId, string $missedDate, string $reason = ''): array
    {
        $db = App::getInstance()->db();

        $attendance = $db->selectOne(
            "SELECT id FROM sa_training_attendance
             WHERE group_id = ? AND player_id = ? AND session_date = ? AND status IN ('absent','excused')",
            [$groupId, $playerId, $missedDate]
        );
        if (!$attendance) {
            return ['success' => false, 'error' => 'لا يوجد سجل غياب لهذا التاريخ'];
        }

        $existing = $db->selectOne(
            "SELECT id FROM sa_makeup_sessions
             WHERE player_id = ? AND original_group_id = ? AND missed_session_date = ? AND status NOT IN ('cancelled','expired')",
            [$playerId, $groupId, $missedDate]
        );
        if ($existing) {
            return ['success' => false, 'error' => 'يوجد بالفعل حصة تعويضية لهذا الغياب'];
        }

        $expiryDaysRow = $db->selectOne(
            "SELECT config_value FROM system_config WHERE config_key = 'sa.makeup_expiry_days'",
            []
        );
        $expiryDays = (int) ($expiryDaysRow['config_value'] ?? 30);
        $expiresAt = date('Y-m-d', strtotime($missedDate . " +{$expiryDays} days"));

        $employeeId = (int) (App::getInstance()->session()->get('employee_id') ?? 0);

        $id = $db->insert('sa_makeup_sessions', [
            'player_id'           => $playerId,
            'original_group_id'   => $groupId,
            'missed_session_date' => $missedDate,
            'missed_reason'       => $reason ?: null,
            'status'              => 'eligible',
            'expires_at'          => $expiresAt,
            'created_at'          => date('Y-m-d H:i:s'),
            'updated_at'          => date('Y-m-d H:i:s'),
            'created_by'          => $employeeId,
        ]);

        return ['success' => true, 'makeup_id' => $id, 'expires_at' => $expiresAt];
    }

    public static function schedule(int $makeupId, int $makeupGroupId, string $makeupDate): array
    {
        $db = App::getInstance()->db();

        $makeup = $db->selectOne(
            "SELECT * FROM sa_makeup_sessions WHERE id = ? AND status = 'eligible'",
            [$makeupId]
        );
        if (!$makeup) {
            return ['success' => false, 'error' => 'الحصة التعويضية غير متاحة للجدولة'];
        }

        if ($makeupDate > $makeup['expires_at']) {
            return ['success' => false, 'error' => 'تاريخ التعويض بعد تاريخ انتهاء الصلاحية'];
        }

        $group = $db->selectOne(
            "SELECT id, current_count, max_capacity FROM sa_groups WHERE id = ? AND status = ? AND is_archived = 0",
            [$makeupGroupId, SaConstants::GROUP_ACTIVE]
        );
        if (!$group) {
            return ['success' => false, 'error' => 'المجموعة المستهدفة غير موجودة أو غير نشطة'];
        }

        $dayOfWeek = (int) date('w', strtotime($makeupDate));
        $hasSession = $db->selectOne(
            "SELECT id FROM sa_group_schedule WHERE group_id = ? AND day_of_week = ? AND is_active = 1",
            [$makeupGroupId, $dayOfWeek]
        );
        if (!$hasSession) {
            return ['success' => false, 'error' => 'لا يوجد تمرين للمجموعة في هذا اليوم'];
        }

        $employeeId = (int) (App::getInstance()->session()->get('employee_id') ?? 0);

        $db->update('sa_makeup_sessions', [
            'makeup_group_id' => $makeupGroupId,
            'makeup_date'     => $makeupDate,
            'status'          => 'scheduled',
            'scheduled_by'    => $employeeId,
            'updated_at'      => date('Y-m-d H:i:s'),
        ], 'id = ?', [$makeupId]);

        return ['success' => true];
    }

    public static function complete(int $makeupId): array
    {
        $db = App::getInstance()->db();

        $makeup = $db->selectOne(
            "SELECT * FROM sa_makeup_sessions WHERE id = ? AND status = 'scheduled'",
            [$makeupId]
        );
        if (!$makeup) {
            return ['success' => false, 'error' => 'الحصة التعويضية غير مجدولة'];
        }

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

        $db->insert('sa_training_attendance', [
            'group_id'          => (int) $makeup['makeup_group_id'],
            'player_id'         => (int) $makeup['player_id'],
            'session_date'      => $makeup['makeup_date'],
            'day_of_week'       => (int) date('w', strtotime($makeup['makeup_date'])),
            'status'            => 'makeup',
            'makeup_session_id' => $makeupId,
            'recorded_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 ['success' => true];
    }

    public static function cancel(int $makeupId): array
    {
        $db = App::getInstance()->db();

        $makeup = $db->selectOne(
            "SELECT id FROM sa_makeup_sessions WHERE id = ? AND status IN ('eligible','scheduled')",
            [$makeupId]
        );
        if (!$makeup) {
            return ['success' => false, 'error' => 'الحصة التعويضية غير قابلة للإلغاء'];
        }

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

        return ['success' => true];
    }

    public static function expireOverdue(): array
    {
        $db = App::getInstance()->db();
        $today = date('Y-m-d');

        $result = $db->query(
            "UPDATE sa_makeup_sessions SET status = 'expired', updated_at = NOW()
             WHERE status IN ('eligible','scheduled') AND expires_at < ?",
            [$today]
        );

        return ['success' => true, 'expired_count' => $result->rowCount()];
    }

    public static function getPlayerMakeups(int $playerId, ?string $status = null): array
    {
        $db = App::getInstance()->db();

        $where = "ms.player_id = ?";
        $params = [$playerId];

        if ($status) {
            $where .= " AND ms.status = ?";
            $params[] = $status;
        }

        return $db->select(
            "SELECT ms.*, g1.name_ar as original_group_name, g2.name_ar as makeup_group_name
             FROM sa_makeup_sessions ms
             LEFT JOIN sa_groups g1 ON g1.id = ms.original_group_id
             LEFT JOIN sa_groups g2 ON g2.id = ms.makeup_group_id
             WHERE {$where}
             ORDER BY ms.created_at DESC",
            $params
        );
    }
}
