<?php

declare(strict_types=1);

namespace App\Framework\Metrics;

use App\Framework\Core\ValueObjects\Timestamp;

/**
 * Represents a single metric with its metadata and value
 */
final readonly class Metric
{
    /**
     * @param array<string, string> $labels
     */
    public function __construct(
        public string $name,
        public float $value,
        public MetricType $type,
        public ?string $help = null,
        public array $labels = [],
        public ?string $unit = null,
        public ?Timestamp $timestamp = null
    ) {
    }

    public function withLabel(string $key, string $value): self
    {
        return new self(
            $this->name,
            $this->value,
            $this->type,
            $this->help,
            array_merge($this->labels, [$key => $value]),
            $this->unit,
            $this->timestamp
        );
    }

    public function withValue(float $value): self
    {
        return new self(
            $this->name,
            $value,
            $this->type,
            $this->help,
            $this->labels,
            $this->unit,
            $this->timestamp
        );
    }

    public function withTimestamp(Timestamp $timestamp): self
    {
        return new self(
            $this->name,
            $this->value,
            $this->type,
            $this->help,
            $this->labels,
            $this->unit,
            $timestamp
        );
    }

    /**
     * Get formatted label string for Prometheus format
     */
    public function getFormattedLabels(): string
    {
        if (empty($this->labels)) {
            return '';
        }

        // Sort labels alphabetically for Prometheus format consistency
        $sortedLabels = $this->labels;
        ksort($sortedLabels);

        $parts = [];
        foreach ($sortedLabels as $key => $value) {
            // Escape special characters in label values
            $escapedValue = str_replace(['\\', '"', "\n"], ['\\\\', '\\"', '\\n'], $value);
            $parts[] = sprintf('%s="%s"', $key, $escapedValue);
        }

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

    /**
     * Convert metric to array representation
     */
    public function toArray(): array
    {
        $data = [
            'name' => $this->name,
            'value' => $this->value,
            'type' => $this->type->value,
        ];

        if ($this->help !== null) {
            $data['help'] = $this->help;
        }

        if (! empty($this->labels)) {
            $data['labels'] = $this->labels;
        }

        if ($this->unit !== null) {
            $data['unit'] = $this->unit;
        }

        if ($this->timestamp !== null) {
            $data['timestamp'] = $this->timestamp->toIso8601();
        }

        return $data;
    }
}
