<?php
declare(strict_types=1);

namespace App\Modules\Installments\Services;

use App\Core\App;
use App\Core\EventBus;
use App\Core\Logger;

final class DefaultChecker
{
    private const DEFAULT_GRACE_DAYS = 90;

    public static function run(): array
    {
        $db = App::getInstance()->db();
        $results = ['plans_defaulted' => 0, 'members_dropped' => 0, 'errors' => []];

        $defaultedPlans = $db->select(
            "SELECT ip.id as plan_id, ip.member_id, ip.status as plan_status,
                    COUNT(isi.id) as overdue_count
             FROM installment_plans ip
             JOIN installment_schedule isi ON isi.installment_plan_id = ip.id
             WHERE ip.status = 'active'
               AND isi.status = 'pending'
               AND isi.due_date < DATE_SUB(NOW(), INTERVAL ? DAY)
             GROUP BY ip.id, ip.member_id, ip.status
             HAVING overdue_count >= 3",
            [self::DEFAULT_GRACE_DAYS]
        );

        foreach ($defaultedPlans as $plan) {
            $planId = (int) $plan['plan_id'];
            $memberId = (int) $plan['member_id'];

            try {
                // Mark plan as defaulted
                $db->query(
                    "UPDATE installment_plans SET status = 'defaulted', updated_at = NOW() WHERE id = ?",
                    [$planId]
                );

                // Mark all pending items as overdue
                $db->query(
                    "UPDATE installment_schedule SET status = 'overdue', updated_at = NOW()
                     WHERE installment_plan_id = ? AND status = 'pending'",
                    [$planId]
                );

                $results['plans_defaulted']++;

                // Drop the member
                $member = $db->selectOne(
                    "SELECT status FROM members WHERE id = ? AND is_archived = 0",
                    [$memberId]
                );

                if ($member && $member['status'] === 'active') {
                    $db->query(
                        "UPDATE members SET status = 'dropped', updated_at = NOW() WHERE id = ?",
                        [$memberId]
                    );
                    $results['members_dropped']++;

                    EventBus::dispatch('member.dropped', [
                        'member_id'       => $memberId,
                        'reason'          => 'عدم الالتزام بسداد الأقساط المستحقة',
                        'installment_plan_id' => $planId,
                    ]);

                    Logger::info("Member dropped for installment default", [
                        'member_id' => $memberId,
                        'plan_id'   => $planId,
                    ]);
                }
            } catch (\Throwable $e) {
                $results['errors'][] = "Plan #{$planId}: " . $e->getMessage();
                Logger::error("DefaultChecker error", ['plan_id' => $planId, 'error' => $e->getMessage()]);
            }
        }

        return $results;
    }
}
