<?php

declare(strict_types=1);

final class CooldownCalculator
{
    /**
     * محاسبه فاصله تا Reminder بعدی
     */
    public function calculate(
        ReminderDecision $decision,
        array $row
    ): int {

        $cooldown = $this->baseCooldown($row);

        $cooldown = $this->applyReminderPenalty(
            $cooldown,
            $row
        );

        $cooldown = $this->applyDeadlinePressure(
            $cooldown,
            $row
        );

        $cooldown = $this->applyScoreAdjustment(
            $cooldown,
            $decision
        );

        return max(
            15 * 60,
            (int)$cooldown
        );
    }

    /**
     * فاصله پایه هر مرحله
     */
    private function baseCooldown(array $row): int
    {
        return match ($row['current_step']) {

            'start' => 30 * 60,

            'ign' => 45 * 60,

            'game_id' => 60 * 60,

            'force_join',
            'private_channel' => 90 * 60,

            'referral' => 2 * 60 * 60,

            'payment' => 3 * 60 * 60,

            default => 60 * 60,
        };
    }

    /**
     * هر Reminder فاصله را بیشتر می‌کند
     */
    private function applyReminderPenalty(
        int $cooldown,
        array $row
    ): int {

        $count = (int)$row['reminder_count'];

        return match ($count) {

            0 => $cooldown,

            1 => $cooldown + 30 * 60,

            2 => $cooldown + 90 * 60,

            3 => $cooldown + 3 * 60 * 60,

            default => $cooldown + 6 * 60 * 60,
        };
    }

    /**
     * نزدیک شدن به Deadline
     */
    private function applyDeadlinePressure(
        int $cooldown,
        array $row
    ): int {

        if (empty($row['deadline'])) {
            return $cooldown;
        }

        $remaining = strtotime($row['deadline']) - time();

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

        if ($remaining <= 3600) {

            return (int)($cooldown * 0.15);
        }

        if ($remaining <= 6 * 3600) {

            return (int)($cooldown * 0.30);
        }

        if ($remaining <= 12 * 3600) {

            return (int)($cooldown * 0.50);
        }

        if ($remaining <= 24 * 3600) {

            return (int)($cooldown * 0.70);
        }

        if ($remaining <= 3 * 86400) {

            return (int)($cooldown * 0.85);
        }

        return $cooldown;
    }

    /**
     * امتیاز بالا = فاصله کمتر
     */
    private function applyScoreAdjustment(
        int $cooldown,
        ReminderDecision $decision
    ): int {

        if ($decision->score >= 200) {

            return (int)($cooldown * 0.50);
        }

        if ($decision->score >= 170) {

            return (int)($cooldown * 0.70);
        }

        if ($decision->score >= 140) {

            return (int)($cooldown * 0.85);
        }

        return $cooldown;
    }
}