<?php

declare(strict_types=1);

namespace App\Framework\Database\Indexing\ValueObjects;

/**
 * Value Object representing an index optimization recommendation
 */
final readonly class IndexRecommendation
{
    public function __construct(
        public string $tableName,
        public array $columns,
        public IndexType $indexType,
        public string $reason,
        public RecommendationPriority $priority,
        public float $estimatedSpeedup,
        public int $affectedQueries,
        public ?string $migrationSql = null
    ) {
        if (empty($columns)) {
            throw new \InvalidArgumentException('Columns array cannot be empty');
        }

        if ($estimatedSpeedup < 1.0) {
            throw new \InvalidArgumentException('Estimated speedup must be >= 1.0');
        }

        if ($affectedQueries < 0) {
            throw new \InvalidArgumentException('Affected queries cannot be negative');
        }
    }

    public function getIndexName(): IndexName
    {
        $columnsPart = implode('_', array_map(
            fn(string $col) => strtolower($col),
            $this->columns
        ));

        $name = "idx_{$this->tableName}_{$columnsPart}";

        // Truncate if too long (max 64 chars)
        if (strlen($name) > 64) {
            $name = substr($name, 0, 61) . '_' . substr(md5($name), 0, 2);
        }

        return new IndexName($name);
    }

    public function getColumnsString(): string
    {
        return implode(', ', $this->columns);
    }

    public function isComposite(): bool
    {
        return count($this->columns) > 1;
    }

    public function toArray(): array
    {
        return [
            'table_name' => $this->tableName,
            'columns' => $this->columns,
            'index_name' => $this->getIndexName()->toString(),
            'index_type' => $this->indexType->value,
            'reason' => $this->reason,
            'priority' => $this->priority->value,
            'estimated_speedup' => $this->estimatedSpeedup,
            'affected_queries' => $this->affectedQueries,
            'is_composite' => $this->isComposite(),
            'migration_sql' => $this->migrationSql
        ];
    }
}

/**
 * Enum representing recommendation priority levels
 */
enum RecommendationPriority: string
{
    case CRITICAL = 'critical';  // >10x speedup or >100 affected queries
    case HIGH = 'high';          // >5x speedup or >50 affected queries
    case MEDIUM = 'medium';      // >2x speedup or >20 affected queries
    case LOW = 'low';            // <2x speedup or <20 affected queries

    public static function fromMetrics(float $speedup, int $affectedQueries): self
    {
        if ($speedup >= 10.0 || $affectedQueries >= 100) {
            return self::CRITICAL;
        }

        if ($speedup >= 5.0 || $affectedQueries >= 50) {
            return self::HIGH;
        }

        if ($speedup >= 2.0 || $affectedQueries >= 20) {
            return self::MEDIUM;
        }

        return self::LOW;
    }

    public function getColor(): string
    {
        return match ($this) {
            self::CRITICAL => 'red',
            self::HIGH => 'orange',
            self::MEDIUM => 'yellow',
            self::LOW => 'green',
        };
    }
}
