<?php

/**
 * Хелпер для роботи з часовими поясами
 * Обгортка над TimezoneManager
 *
 * @package Flowaxy\Support\Helpers
 * @version 1.0.0 Alpha prerelease
 */

declare(strict_types=1);

namespace Flowaxy\Support\Helpers;

use Flowaxy\Support\Managers\TimezoneManager;

final class TimezoneHelper
{
    /**
     * Встановити часовий пояс
     *
     * @param string $timezone
     * @return bool
     */
    public static function set(string $timezone): bool
    {
        if (!self::isValid($timezone)) {
            return false;
        }

        return date_default_timezone_set($timezone);
    }

    /**
     * Отримати поточний часовий пояс
     *
     * @return string
     */
    public static function get(): string
    {
        return date_default_timezone_get();
    }

    /**
     * Конвертувати дату в інший часовий пояс
     *
     * @param \DateTime|string|int $date
     * @param string $fromTimezone
     * @param string $toTimezone
     * @return \DateTime|false
     */
    public static function convert(\DateTime|string|int $date, string $fromTimezone, string $toTimezone): \DateTime|false
    {
        if (!self::isValid($fromTimezone) || !self::isValid($toTimezone)) {
            return false;
        }

        if (is_string($date)) {
            $date = new \DateTime($date, new \DateTimeZone($fromTimezone));
        } elseif (is_int($date)) {
            $date = (new \DateTime())->setTimestamp($date)->setTimezone(new \DateTimeZone($fromTimezone));
        }

        return $date->setTimezone(new \DateTimeZone($toTimezone));
    }

    /**
     * Отримати список всіх часових поясів
     *
     * @return array<int, string>
     */
    public static function list(): array
    {
        return timezone_identifiers_list();
    }

    /**
     * Перевірити, чи часовий пояс валідний
     *
     * @param string $timezone
     * @return bool
     */
    public static function isValid(string $timezone): bool
    {
        return in_array($timezone, timezone_identifiers_list(), true);
    }

    /**
     * Отримати зміщення часового поясу
     *
     * @param string $timezone
     * @return int|false
     */
    public static function getOffset(string $timezone): int|false
    {
        if (!self::isValid($timezone)) {
            return false;
        }

        $dateTime = new \DateTime('now', new \DateTimeZone($timezone));

        return $dateTime->getOffset();
    }

    /**
     * Отримати назву часового поясу
     *
     * @param string $timezone
     * @return string
     */
    public static function getName(string $timezone): string
    {
        return $timezone;
    }

    /**
     * Отримати абревіатуру часового поясу
     *
     * @param string $timezone
     * @return string
     */
    public static function getAbbreviation(string $timezone): string
    {
        $dateTime = new \DateTime('now', new \DateTimeZone($timezone));

        return $dateTime->format('T');
    }

    /**
     * Отримати поточну дату та час в часовому поясі
     *
     * @param string|null $timezone
     * @return \DateTime
     */
    public static function now(?string $timezone = null): \DateTime
    {
        if ($timezone !== null && self::isValid($timezone)) {
            return new \DateTime('now', new \DateTimeZone($timezone));
        }

        return new \DateTime();
    }

    /**
     * Форматувати дату в часовому поясі
     *
     * @param \DateTime|string|int $date
     * @param string $format
     * @param string|null $timezone
     * @return string|false
     */
    public static function format(\DateTime|string|int $date, string $format = 'Y-m-d H:i:s', ?string $timezone = null): string|false
    {
        if (is_string($date)) {
            $date = new \DateTime($date);
        } elseif (is_int($date)) {
            $date = (new \DateTime())->setTimestamp($date);
        }

        if ($timezone !== null && self::isValid($timezone)) {
            $date->setTimezone(new \DateTimeZone($timezone));
        }

        return $date->format($format);
    }
}
