<?php

declare(strict_types=1);

final class SmartReminderEngine
{
    private ReminderRules $rules;
    private ReminderScorer $scorer;
    private ReminderPolicy $policy;

    public function __construct()
    {
        $this->rules = new ReminderRules();
        $this->scorer = new ReminderScorer();
        $this->policy = new ReminderPolicy();
    }

    /**
     * تصمیم نهایی Reminder
     */
    public function decide(array $row): ReminderDecision
    {
        // مرحله ۱: محاسبه امتیاز
        $decision = $this->scorer->score($row);

        // مرحله ۲: تعیین سطح ارسال
        $decision = $this->policy->resolve($decision);

        // مرحله ۳: اعمال قوانین قطعی
        if (!$this->rules->passes($row, $decision)) {
            return $decision;
        }

        return $decision;
    }

    /**
     * زمان تقریبی موردنیاز برای تکمیل هر مرحله (ثانیه)
     */
    private function getExpectedCompletionTime(string $step): int
    {
        return match ($step) {

            'start'           => 60,        // 1 دقیقه

            'ign'             => 180,       // 3 دقیقه

            'game_id'         => 300,       // 5 دقیقه

            'private_channel',
            'force_join'      => 120,       // 2 دقیقه

            'referral'        => 21600,     // 6 ساعت

            'payment'         => 43200,     // 12 ساعت

            default           => 600
        };
    }

        /**
     * فشار ناشی از نزدیک شدن به Deadline
     * خروجی: ثانیه‌ای که از Delay کم می‌شود.
     */
    private function getDeadlineUrgency(?string $deadline, string $step): int
    {
        if (empty($deadline)) {
            return 0;
        }

        $remaining = strtotime($deadline) - time();

        if ($remaining <= 0) {
            return 0;
        }

        $expected = $this->getExpectedCompletionTime($step);

        /*
        * اگر زمان باقی‌مانده کمتر از دو برابر
        * زمان موردنیاز تکمیل باشد،
        * باید یادآوری زودتر ارسال شود.
        */

        if ($remaining <= ($expected * 2)) {

            return (int)($expected * 0.5);

        }

        if ($remaining <= ($expected * 4)) {

            return (int)($expected * 0.25);

        }

        return 0;
    }

    /**
     * سازگاری با کدهای قدیمی
     */
    public function shouldSend(array $row): bool
    {
        return $this->decide($row)->send;
    }
}