<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Services;

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

final class SubscriptionGeneratorService
{
    public static function generateForMonth(string $yearMonth): array
    {
        $db = App::getInstance()->db();

        $periodStart = $yearMonth . '-01';
        $periodEnd = date('Y-m-t', strtotime($periodStart));

        $groupPlayers = $db->select(
            "SELECT gp.player_id, gp.group_id, gp.enrolled_at, gp.paused_months,
                    sp.player_type, sp.full_name_ar as player_name,
                    sp.medical_status, sp.medical_expiry_date,
                    p.monthly_fee_member, p.monthly_fee_nonmember, g.name_ar as group_name
             FROM sa_group_players gp
             JOIN sa_players sp ON sp.id = gp.player_id
             JOIN sa_groups g ON g.id = gp.group_id
             JOIN sa_programs p ON p.id = g.program_id
             WHERE gp.status = ?
               AND g.status = ? AND g.is_archived = 0",
            [SaConstants::STATUS_ACTIVE, SaConstants::GROUP_ACTIVE]
        );

        $existingSubs = $db->select(
            "SELECT player_id, group_id FROM sa_subscriptions WHERE period_start = ?",
            [$periodStart]
        );
        $existingSet = [];
        foreach ($existingSubs as $es) {
            $existingSet[$es['player_id'] . ':' . $es['group_id']] = true;
        }

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

        foreach ($groupPlayers as $gp) {
            $key = $gp['player_id'] . ':' . $gp['group_id'];
            if (isset($existingSet[$key])) {
                $skipped++;
                continue;
            }

            $pausedMonths = json_decode($gp['paused_months'] ?? '[]', true) ?: [];
            if (in_array($yearMonth, $pausedMonths, true)) {
                $skipped++;
                continue;
            }

            $medicalVerified = self::checkMedicalForRenewal($gp);

            $amount = $gp['player_type'] === SaConstants::PLAYER_MEMBER
                ? (float) $gp['monthly_fee_member']
                : (float) $gp['monthly_fee_nonmember'];

            // Proration: first month + enrolled after 15th = half fee
            $isFirstMonth = !$db->selectOne(
                "SELECT id FROM sa_subscriptions WHERE player_id = ? AND group_id = ? AND period_start < ? LIMIT 1",
                [(int) $gp['player_id'], (int) $gp['group_id'], $periodStart]
            );

            if ($isFirstMonth && !empty($gp['enrolled_at'])) {
                $enrollmentDay = (int) date('j', strtotime($gp['enrolled_at']));
                if ($enrollmentDay > 15) {
                    $amount = round($amount / 2, 2);
                }
            }

            $subNumber = NumberGeneratorService::subscriptionNumber();

            $db->insert('sa_subscriptions', [
                'subscription_number' => $subNumber,
                'player_id'           => (int) $gp['player_id'],
                'group_id'            => (int) $gp['group_id'],
                'period_start'        => $periodStart,
                'period_end'          => $periodEnd,
                'amount'              => $amount,
                'discount_amount'     => 0.00,
                'final_amount'        => $amount,
                'payment_status'      => SaConstants::PAYMENT_UNPAID,
                'paid_amount'         => 0.00,
                'auto_generated'      => 1,
                'medical_verified'    => $medicalVerified ? 1 : 0,
                'created_at'          => date('Y-m-d H:i:s'),
                'updated_at'          => date('Y-m-d H:i:s'),
                'created_by'          => $employeeId,
            ]);

            if (!$medicalVerified) {
                $medicalBlocked++;
            }
            $generated++;
        }

        return [
            'success'         => true,
            'generated'       => $generated,
            'skipped'         => $skipped,
            'medical_blocked' => $medicalBlocked,
            'month'           => $yearMonth,
        ];
    }

    private static function checkMedicalForRenewal(array $gp): bool
    {
        if (in_array($gp['medical_status'], [SaConstants::MEDICAL_FIT, SaConstants::MEDICAL_CONDITIONAL], true)) {
            if (!empty($gp['medical_expiry_date']) && $gp['medical_expiry_date'] < date('Y-m-d')) {
                return false;
            }
            return true;
        }
        return false;
    }
}
