<?php

namespace ZenoChatbot\Services\Scheduler;

if (!defined('ABSPATH')) {
    exit;
}

class RepeatSchedule
{
    /** @var PendingSchedule */
    private $pending;

    public static function create(PendingSchedule $pending): RepeatSchedule
    {
        $instance = new static();
        $instance->pending = $pending;

        return $instance;
    }

    public function hourly(): PendingSchedule
    {
        return $this->pending->setRecurrence('interval', HOUR_IN_SECONDS);
    }

    public function daily(): PendingSchedule
    {
        return $this->pending->setRecurrence('interval', DAY_IN_SECONDS);
    }

    public function weekly(): PendingSchedule
    {
        return $this->pending->setRecurrence('interval', WEEK_IN_SECONDS);
    }

    public function monthly(): PendingSchedule
    {
        return $this->pending->setRecurrence('cron', $this->buildMonthlyPattern());
    }

    public function quarterly(): PendingSchedule
    {
        return $this->pending->setRecurrence('cron', $this->buildQuarterlyPattern());
    }

    public function yearly(): PendingSchedule
    {
        return $this->pending->setRecurrence('cron', $this->buildYearlyPattern());
    }

    public function on($customInterval): PendingSchedule
    {
        if (is_int($customInterval) || is_float($customInterval) || (is_string($customInterval) && ctype_digit(trim($customInterval)))) {
            return $this->pending->setRecurrence('interval', max(1, (int) $customInterval));
        }

        if (!is_string($customInterval)) {
            return $this->pending;
        }

        $customInterval = trim($customInterval);
        if ($customInterval === '') {
            return $this->pending;
        }

        $seconds = Scheduler::toSeconds($customInterval);
        if ($seconds > 0) {
            return $this->pending->setRecurrence('interval', $seconds);
        }

        // Allow direct cron expression for advanced custom schedules.
        if (preg_match('/^\S+\s+\S+\s+\S+\s+\S+\s+\S+$/', $customInterval) === 1) {
            return $this->pending->setRecurrence('cron', $customInterval);
        }

        return $this->pending;
    }

    private function buildMonthlyPattern(): string
    {
        $ts = $this->pending->previewTimestamp();
        $minute = (int) gmdate('i', $ts);
        $hour = (int) gmdate('G', $ts);
        $day = (int) gmdate('j', $ts);

        return sprintf('%d %d %d * *', $minute, $hour, $day);
    }

    private function buildQuarterlyPattern(): string
    {
        $ts = $this->pending->previewTimestamp();
        $minute = (int) gmdate('i', $ts);
        $hour = (int) gmdate('G', $ts);
        $day = (int) gmdate('j', $ts);
        $startMonth = (int) gmdate('n', $ts);

        $months = [];
        for ($i = 0; $i < 4; $i++) {
            $months[] = (string) (((($startMonth - 1) + ($i * 3)) % 12) + 1);
        }

        return sprintf('%d %d %d %s *', $minute, $hour, $day, implode(',', $months));
    }

    private function buildYearlyPattern(): string
    {
        $ts = $this->pending->previewTimestamp();
        $minute = (int) gmdate('i', $ts);
        $hour = (int) gmdate('G', $ts);
        $day = (int) gmdate('j', $ts);
        $month = (int) gmdate('n', $ts);

        return sprintf('%d %d %d %d *', $minute, $hour, $day, $month);
    }
}
