<?php

declare(strict_types=1);

namespace App\Framework\Database\ValueObjects;

use App\Framework\Database\Validation\DatabaseIdentifierValidator;
use InvalidArgumentException;

/**
 * Value Object representing a database column name
 *
 * Provides type safety, validation, and SQL injection prevention for column names.
 * Ensures column names follow standard SQL naming conventions.
 *
 * Features:
 * - Alphanumeric validation with underscores
 * - SQL keyword detection
 * - Maximum length enforcement (64 chars - MySQL standard)
 * - Case-insensitive comparison
 * - Platform-specific quoting support
 */
final readonly class ColumnName
{
    private function __construct(
        public string $value
    ) {
        $this->validate();
    }

    /**
     * Create from string
     */
    public static function fromString(string $columnName): self
    {
        return new self($columnName);
    }

    /**
     * Convert to string
     */
    public function toString(): string
    {
        return $this->value;
    }

    /**
     * Magic __toString for convenient string conversion
     */
    public function __toString(): string
    {
        return $this->value;
    }

    /**
     * Compare for equality (case-insensitive)
     */
    public function equals(self $other): bool
    {
        return strcasecmp($this->value, $other->value) === 0;
    }

    /**
     * Check if column name matches pattern (case-insensitive)
     */
    public function matches(string $pattern): bool
    {
        return fnmatch($pattern, $this->value, FNM_CASEFOLD);
    }

    /**
     * Get quoted identifier for safe SQL usage
     *
     * Platform-specific quoting:
     * - MySQL: `column_name`
     * - PostgreSQL: "column_name"
     * - SQLite: "column_name"
     */
    public function quoted(string $platform = 'mysql'): string
    {
        return match (strtolower($platform)) {
            'mysql' => "`{$this->value}`",
            'postgresql', 'postgres', 'pgsql' => "\"{$this->value}\"",
            'sqlite' => "\"{$this->value}\"",
            default => "`{$this->value}`", // Default to MySQL style
        };
    }

    /**
     * Get fully qualified column name (table.column)
     */
    public function qualified(TableName $tableName, string $platform = 'mysql'): string
    {
        return $tableName->quoted($platform) . '.' . $this->quoted($platform);
    }

    /**
     * Check if column name is a reserved SQL keyword
     */
    public function isReservedKeyword(): bool
    {
        return (new DatabaseIdentifierValidator())->isReservedKeyword($this->value);
    }

    /**
     * Get lowercase version (useful for case-insensitive comparisons)
     */
    public function toLower(): string
    {
        return strtolower($this->value);
    }

    /**
     * Check if column name ends with given suffix (e.g., '_id', '_at')
     */
    public function hasSuffix(string $suffix): bool
    {
        return str_ends_with($this->value, $suffix);
    }

    /**
     * Check if this appears to be a foreign key column
     */
    public function isForeignKey(): bool
    {
        return $this->hasSuffix('_id') && $this->value !== 'id';
    }

    /**
     * Check if this appears to be a timestamp column
     */
    public function isTimestamp(): bool
    {
        return $this->hasSuffix('_at')
            || in_array($this->value, ['created_at', 'updated_at', 'deleted_at'], true);
    }

    /**
     * Validate column name
     *
     * @throws InvalidArgumentException if validation fails
     */
    private function validate(): void
    {
        (new DatabaseIdentifierValidator())->validate($this->value, 'column');
    }
}
