<?php

declare(strict_types=1);

namespace App\Framework\Database\Platform\Enums;

/**
 * Database column types abstraction
 */
enum ColumnType: string
{
    // Numeric types
    case TINY_INTEGER = 'tinyint';
    case SMALL_INTEGER = 'smallint';
    case INTEGER = 'integer';
    case BIG_INTEGER = 'bigint';
    case DECIMAL = 'decimal';
    case FLOAT = 'float';
    case DOUBLE = 'double';
    case BOOLEAN = 'boolean';

    // String types
    case CHAR = 'char';
    case VARCHAR = 'varchar';
    case TEXT = 'text';
    case MEDIUM_TEXT = 'mediumtext';
    case LONG_TEXT = 'longtext';

    // Binary types
    case BINARY = 'binary';
    case VARBINARY = 'varbinary';
    case BLOB = 'blob';
    case MEDIUM_BLOB = 'mediumblob';
    case LONG_BLOB = 'longblob';

    // Date/Time types
    case DATE = 'date';
    case TIME = 'time';
    case DATETIME = 'datetime';
    case TIMESTAMP = 'timestamp';
    case YEAR = 'year';

    // JSON type
    case JSON = 'json';

    // UUID types
    case UUID = 'uuid';
    case ULID = 'ulid';

    public function requiresLength(): bool
    {
        return match($this) {
            self::CHAR, self::VARCHAR, self::BINARY, self::VARBINARY => true,
            default => false
        };
    }

    public function requiresPrecision(): bool
    {
        return match($this) {
            self::DECIMAL, self::FLOAT, self::DOUBLE => true,
            default => false
        };
    }

    public function isNumeric(): bool
    {
        return match($this) {
            self::TINY_INTEGER, self::SMALL_INTEGER, self::INTEGER, self::BIG_INTEGER,
            self::DECIMAL, self::FLOAT, self::DOUBLE, self::BOOLEAN => true,
            default => false
        };
    }

    public function isTextual(): bool
    {
        return match($this) {
            self::CHAR, self::VARCHAR, self::TEXT, self::MEDIUM_TEXT, self::LONG_TEXT, self::JSON => true,
            default => false
        };
    }

    public function isBinary(): bool
    {
        return match($this) {
            self::BINARY, self::VARBINARY, self::BLOB, self::MEDIUM_BLOB, self::LONG_BLOB,
            self::UUID, self::ULID => true,
            default => false
        };
    }

    public function isTemporal(): bool
    {
        return match($this) {
            self::DATE, self::TIME, self::DATETIME, self::TIMESTAMP, self::YEAR => true,
            default => false
        };
    }
}
