<?php

declare(strict_types=1);

namespace App\Framework\Database\Platform\ValueObjects;

/**
 * Represents table creation options
 */
final readonly class TableOptions
{
    public function __construct(
        public string $engine = 'InnoDB',
        public string $charset = 'utf8mb4',
        public string $collation = 'utf8mb4_unicode_ci',
        public ?string $comment = null,
        public ?int $autoIncrementStart = null,
        public bool $temporary = false,
        public bool $ifNotExists = true,
        public array $partitioning = [],
        public array $customOptions = []
    ) {
    }

    public static function default(): self
    {
        return new self();
    }

    public static function temporary(): self
    {
        return new self(temporary: true);
    }

    public static function myISAM(): self
    {
        return new self(engine: 'MyISAM');
    }

    public static function memory(): self
    {
        return new self(engine: 'MEMORY');
    }

    public function withComment(string $comment): self
    {
        return new self(
            engine: $this->engine,
            charset: $this->charset,
            collation: $this->collation,
            comment: $comment,
            autoIncrementStart: $this->autoIncrementStart,
            temporary: $this->temporary,
            ifNotExists: $this->ifNotExists,
            partitioning: $this->partitioning,
            customOptions: $this->customOptions
        );
    }

    public function withCharset(string $charset, ?string $collation = null): self
    {
        return new self(
            engine: $this->engine,
            charset: $charset,
            collation: $collation ?? $this->collation,
            comment: $this->comment,
            autoIncrementStart: $this->autoIncrementStart,
            temporary: $this->temporary,
            ifNotExists: $this->ifNotExists,
            partitioning: $this->partitioning,
            customOptions: $this->customOptions
        );
    }

    public function withCollation(string $collation): self
    {
        return new self(
            engine: $this->engine,
            charset: $this->charset,
            collation: $collation,
            comment: $this->comment,
            autoIncrementStart: $this->autoIncrementStart,
            temporary: $this->temporary,
            ifNotExists: $this->ifNotExists,
            partitioning: $this->partitioning,
            customOptions: $this->customOptions
        );
    }

    public function withEngine(string $engine): self
    {
        return new self(
            engine: $engine,
            charset: $this->charset,
            collation: $this->collation,
            comment: $this->comment,
            autoIncrementStart: $this->autoIncrementStart,
            temporary: $this->temporary,
            ifNotExists: $this->ifNotExists,
            partitioning: $this->partitioning,
            customOptions: $this->customOptions
        );
    }

    public function withIfNotExists(bool $ifNotExists = true): self
    {
        return new self(
            engine: $this->engine,
            charset: $this->charset,
            collation: $this->collation,
            comment: $this->comment,
            autoIncrementStart: $this->autoIncrementStart,
            temporary: $this->temporary,
            ifNotExists: $ifNotExists,
            partitioning: $this->partitioning,
            customOptions: $this->customOptions
        );
    }

    public function withAutoIncrementStart(int $start): self
    {
        return new self(
            engine: $this->engine,
            charset: $this->charset,
            collation: $this->collation,
            comment: $this->comment,
            autoIncrementStart: $start,
            temporary: $this->temporary,
            ifNotExists: $this->ifNotExists,
            partitioning: $this->partitioning,
            customOptions: $this->customOptions
        );
    }

    public function withoutIfNotExists(): self
    {
        return new self(
            engine: $this->engine,
            charset: $this->charset,
            collation: $this->collation,
            comment: $this->comment,
            autoIncrementStart: $this->autoIncrementStart,
            temporary: $this->temporary,
            ifNotExists: false,
            partitioning: $this->partitioning,
            customOptions: $this->customOptions
        );
    }

    public function withCustomOption(string $key, mixed $value): self
    {
        return new self(
            engine: $this->engine,
            charset: $this->charset,
            collation: $this->collation,
            comment: $this->comment,
            autoIncrementStart: $this->autoIncrementStart,
            temporary: $this->temporary,
            ifNotExists: $this->ifNotExists,
            partitioning: $this->partitioning,
            customOptions: array_merge($this->customOptions, [$key => $value])
        );
    }

    public function isUtf8(): bool
    {
        return str_starts_with($this->charset, 'utf8');
    }

    public function supportsFulltext(): bool
    {
        return in_array($this->engine, ['InnoDB', 'MyISAM']);
    }

    public function supportsTransactions(): bool
    {
        return $this->engine === 'InnoDB';
    }

    public function supportsRowLocking(): bool
    {
        return $this->engine === 'InnoDB';
    }
}
