<?php
declare(strict_types=1);

namespace CronJobs;

use App\Core\Database;
use App\Core\EventBus;
use App\Core\Logger;
use App\Modules\Subscriptions\Services\SubscriptionCalculator;

class OverdueFineJob
{
    private Database $db;
    public function __construct(Database $db) { $this->db = $db; }

    public function shouldRun(): bool
    {
        return (int) date('n') >= 10;
    }

    public function run(): array
    {
        $processed = 0;

        // Mark unpaid subscriptions as overdue
        $overdue = $this->db->select(
            "SELECT s.id, s.member_id, s.total_amount, s.financial_year
             FROM subscriptions s
             WHERE s.status = 'pending' AND s.paid_amount = 0"
        );

        foreach ($overdue as $sub) {
            $this->db->update('subscriptions', [
                'status'     => 'overdue',
                'updated_at' => date('Y-m-d H:i:s'),
            ], '`id` = ? AND `status` = \'pending\'', [(int) $sub['id']]);
            $processed++;
        }

        // Apply calculated fines to overdue subscriptions
        $currentFY = self::currentFinancialYear();
        $membersWithOverdue = $this->db->select(
            "SELECT DISTINCT member_id FROM subscriptions WHERE status = 'overdue'"
        );

        foreach ($membersWithOverdue as $row) {
            try {
                $calc = SubscriptionCalculator::calculateLateFine((int) $row['member_id'], $currentFY);
                foreach ($calc['details'] as $detail) {
                    $this->db->query(
                        "UPDATE subscriptions SET fine_amount = ?, updated_at = NOW()
                         WHERE member_id = ? AND financial_year = ? AND status = 'overdue'",
                        [$detail['fine_amount'], (int) $row['member_id'], $detail['financial_year']]
                    );
                }
            } catch (\Throwable $e) {
                Logger::error("Fine calculation failed for member #{$row['member_id']}: " . $e->getMessage());
            }
        }

        // Drop memberships with 5+ consecutive years unpaid
        $members = $this->db->select(
            "SELECT s.member_id, COUNT(DISTINCT s.financial_year) as unpaid_years
             FROM subscriptions s
             JOIN members m ON m.id = s.member_id AND m.status = 'active' AND m.is_archived = 0
             WHERE s.status IN ('pending','overdue') AND s.paid_amount = 0
             GROUP BY s.member_id
             HAVING unpaid_years >= 5"
        );

        foreach ($members as $m) {
            $this->db->update('members', [
                'status'     => 'dropped',
                'updated_at' => date('Y-m-d H:i:s'),
            ], '`id` = ? AND `status` = \'active\'', [(int) $m['member_id']]);

            if ($this->db->pdo()->rowCount() > 0) {
                Logger::warning("Membership dropped: member #{$m['member_id']} ({$m['unpaid_years']} years)");
                $processed++;

                EventBus::dispatch('member.dropped', [
                    'member_id'    => (int) $m['member_id'],
                    'reason'       => 'تأخر عن سداد الاشتراك السنوي 5 سنوات متتالية',
                    'years_unpaid' => (int) $m['unpaid_years'],
                ]);
            }
        }

        return ['processed' => $processed];
    }

    private static function currentFinancialYear(): string
    {
        $month = (int) date('n');
        $year = (int) date('Y');
        return $month >= 7 ? $year . '/' . ($year + 1) : ($year - 1) . '/' . $year;
    }
}