<?php

declare(strict_types=1);

namespace Plugin\tnt_coupons\src\Helper;

use DateTimeImmutable;

use function array_filter;
use function array_map;
use function array_unique;
use function array_values;
use function count;
use function explode;
use function in_array;
use function trim;

/**
 * Pure, side-effect-free trigger that decides whether a sale/banner may show on the
 * current weekday. Complements DateWindowTrigger: the date window bounds the absolute
 * period, this one bounds the recurring days of week within that period.
 *
 * Days use the ISO-8601 numbering returned by DateTimeImmutable::format('N'):
 *   1 = Monday … 7 = Sunday.
 *
 * Backward-compatible semantics (preserves the pre-schedule behaviour exactly):
 *   - an empty allow-list => no restriction => always active on every weekday.
 * When at least one valid day is configured the banner is active only on those days.
 * Values outside 1..7 are ignored; if nothing valid remains the list is treated as
 * empty (always active) so a mistyped setting can never silently hide a coupon forever.
 *
 * Timezone: the weekday is read from the DateTimeImmutable passed by the caller, which
 * is built consistently with the rest of the plugin (server-local `now`).
 */
final class WeekdayScheduleTrigger
{
    /**
     * @param int[] $allowedDays ISO-8601 weekday numbers (1=Mon … 7=Sun)
     */
    public static function isActive(array $allowedDays, DateTimeImmutable $now): bool
    {
        $allowedDays = self::sanitize($allowedDays);
        if (count($allowedDays) === 0) {
            return true;
        }

        return in_array((int)$now->format('N'), $allowedDays, true);
    }

    /**
     * Parse the stored scalar config value (e.g. "6,7") into ISO weekday numbers.
     *
     * @return int[]
     */
    public static function fromConfig(string $value): array
    {
        if (trim($value) === '') {
            return [];
        }

        $parts = array_map('trim', explode(',', $value));
        $days  = array_map('intval', array_filter($parts, static fn (string $p): bool => $p !== ''));

        return self::sanitize($days);
    }

    /**
     * @param int[] $days
     *
     * @return int[]
     */
    private static function sanitize(array $days): array
    {
        $valid = array_values(array_filter($days, static fn (int $d): bool => $d >= 1 && $d <= 7));

        return array_values(array_unique($valid));
    }
}
