<?php

namespace Components\Common;

/**
 * Date helpers used by BeezUI.
 *
 * Some platforms / DB configurations store “unset” datetime columns using sentinel values.
 * Most commonly this is `0000-00-00 00:00:00`, but some (e.g., ZenCart) use
 * `1000-01-01 00:00:00`. BeezUI should treat both as “empty” when reading/filtering.
 */
class Date
{
    public const ZERO_DATE_MYSQL = '0000-00-00';
    public const ZERO_DATETIME_MYSQL = '0000-00-00 00:00:00';

    public const ZERO_DATE_ZEN = '1000-01-01';
    public const ZERO_DATETIME_ZEN = '1000-01-01 00:00:00';

    /**
     * Return true when the given value is a known “zero”/sentinel date representation
     * or otherwise empty.
     *
     * @param mixed $v
     */
    public static function isZeroDateValue($v, bool $treatStringZeroAsEmpty = true): bool
    {
        if ($v === null) {
            return true;
        }
        if (is_string($v)) {
            $s = trim($v);
            if ($s === '') {
                return true;
            }
            if ($treatStringZeroAsEmpty && $s === '0') {
                return true;
            }
            return in_array($s, [
                self::ZERO_DATE_MYSQL,
                self::ZERO_DATETIME_MYSQL,
                self::ZERO_DATE_ZEN,
                self::ZERO_DATETIME_ZEN,
            ], true);
        }
        return false;
    }

    /**
     * Normalize common sentinel/empty values to null, otherwise return the original value.
     *
     * @param mixed $v
     * @return mixed
     */
    public static function nullIfZero($v)
    {
        return self::isZeroDateValue($v) ? null : $v;
    }

    /**
     * SQL fragment: column is considered "unset" (NULL/''/sentinel values).
     */
    public static function sqlIsUnset(string $column, bool $includeEmptyString = false): string
    {
        $parts = [
            "{$column} IS NULL",
        ];

        if ($includeEmptyString) {
            $parts[] = "{$column} = ''";
        }

        $parts[] = "{$column} = '" . self::ZERO_DATETIME_MYSQL . "'";
        $parts[] = "{$column} = '" . self::ZERO_DATE_MYSQL . "'";
        $parts[] = "{$column} = '" . self::ZERO_DATETIME_ZEN . "'";
        $parts[] = "{$column} = '" . self::ZERO_DATE_ZEN . "'";

        return '(' . implode(' OR ', $parts) . ')';
    }

    /**
     * SQL fragment: column is considered "set" (not NULL/''/sentinel values).
     */
    public static function sqlIsSet(string $column, bool $includeEmptyString = false): string
    {
        $parts = [
            "{$column} IS NOT NULL",
        ];

        if ($includeEmptyString) {
            $parts[] = "{$column} <> ''";
        }

        $parts[] = "{$column} <> '" . self::ZERO_DATETIME_MYSQL . "'";
        $parts[] = "{$column} <> '" . self::ZERO_DATE_MYSQL . "'";
        $parts[] = "{$column} <> '" . self::ZERO_DATETIME_ZEN . "'";
        $parts[] = "{$column} <> '" . self::ZERO_DATE_ZEN . "'";

        return '(' . implode(' AND ', $parts) . ')';
    }
}
