<?php
declare(strict_types=1);

namespace CronJobs;

use App\Core\Database;
use App\Core\Logger;

/**
 * Generates monthly activity subscriptions for all active enrollments.
 * Runs on the 1st of each month.
 */
class ActivitySubGeneratorJob
{
    private Database $db;
    public function __construct(Database $db) { $this->db = $db; }

    public function shouldRun(): bool
    {
        return (int) date('j') === 1;
    }

    public function run(): array
    {
        $month = date('Y-m'); // Current month YYYY-MM
        $ts = date('Y-m-d H:i:s');
        $defaultDueDate = date('Y-m-07'); // 7th of the month
        $processed = 0;
        $skipped = 0;

        // Get all active enrollments with player info
        $enrollments = $this->db->select("
            SELECT ae.id AS enrollment_id, ae.player_id, ae.academy_id, ae.level_id,
                   ae.enrollment_day, ae.season, ae.enrolled_at,
                   p.player_type,
                   a.discipline_id
            FROM academy_enrollments ae
            JOIN players p ON p.id = ae.player_id AND p.is_archived = 0
            JOIN academies a ON a.id = ae.academy_id AND a.is_active = 1
            WHERE ae.status = 'active'
        ");

        foreach ($enrollments as $e) {
            $playerId = (int) $e['player_id'];
            $enrollmentId = (int) $e['enrollment_id'];

            // Check if subscription already exists for this player+month
            $existing = $this->db->selectOne(
                "SELECT id FROM activity_subscriptions WHERE player_id = ? AND enrollment_id = ? AND subscription_month = ?",
                [$playerId, $enrollmentId, $month]
            );
            if ($existing) {
                $skipped++;
                continue;
            }

            // Look up pricing — try academy pricing first, then discipline
            $isMember = ($e['player_type'] === 'member');
            $rateCol = $isMember ? 'member_rate' : 'nonmember_rate';

            $pricing = $this->db->selectOne(
                "SELECT {$rateCol} AS rate FROM activity_pricing WHERE pricing_type = 'academy' AND reference_id = ? AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE())",
                [(int) $e['academy_id']]
            );

            if (!$pricing) {
                $pricing = $this->db->selectOne(
                    "SELECT {$rateCol} AS rate FROM activity_pricing WHERE pricing_type = 'discipline' AND reference_id = ? AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE())",
                    [(int) $e['discipline_id']]
                );
            }

            $baseRate = $pricing ? (string) $pricing['rate'] : '0.00';

            // Half-month logic: if enrollment was after the 15th AND this is the first month
            $isFirstMonth = $this->isFirstSubscriptionMonth($enrollmentId, $month);
            $enrollmentDay = (int) ($e['enrollment_day'] ?? 1);
            $isHalfMonth = ($isFirstMonth && $enrollmentDay > 15) ? 1 : 0;

            $appliedRate = $isHalfMonth ? bcdiv($baseRate, '2', 2) : $baseRate;

            // Due date: for first month with enrollment after 7th, give 7 days from enrollment
            if ($isFirstMonth && $enrollmentDay > 7) {
                $enrolledAt = $e['enrolled_at'] ?? date('Y-m-d');
                $dueDate = date('Y-m-d', strtotime('+7 days', strtotime($enrolledAt)));
            } else {
                $dueDate = $defaultDueDate;
            }

            $this->db->insert('activity_subscriptions', [
                'player_id'          => $playerId,
                'enrollment_id'      => $enrollmentId,
                'discipline_id'      => (int) $e['discipline_id'],
                'subscription_month' => $month,
                'player_type'        => $e['player_type'],
                'base_rate'          => $baseRate,
                'is_half_month'      => $isHalfMonth,
                'applied_rate'       => $appliedRate,
                'discount'           => '0.00',
                'total_amount'       => $appliedRate,
                'status'             => 'pending',
                'due_date'           => $dueDate,
                'created_at'         => $ts,
                'updated_at'         => $ts,
            ]);
            $processed++;
        }

        Logger::info("Activity subscription generation for {$month}: {$processed} created, {$skipped} skipped");
        return ['month' => $month, 'processed' => $processed, 'skipped' => $skipped];
    }

    private function isFirstSubscriptionMonth(int $enrollmentId, string $currentMonth): bool
    {
        $prev = $this->db->selectOne(
            "SELECT id FROM activity_subscriptions WHERE enrollment_id = ? AND subscription_month < ? LIMIT 1",
            [$enrollmentId, $currentMonth]
        );
        return !$prev;
    }
}
