<?php

declare(strict_types=1);

namespace App\Framework\Queue\ValueObjects;

use App\Framework\Core\ValueObjects\Percentage;

/**
 * Value Object representing job progress with percentage and status message
 */
final readonly class JobProgress
{
    public function __construct(
        public Percentage $percentage,
        public string $message,
        public ?array $metadata = null
    ) {
        $this->validate();
    }

    public static function starting(string $message = 'Job starting...'): self
    {
        return new self(Percentage::zero(), $message);
    }

    public static function completed(string $message = 'Job completed successfully'): self
    {
        return new self(Percentage::full(), $message);
    }

    public static function failed(string $message = 'Job failed'): self
    {
        return new self(Percentage::zero(), $message, ['status' => 'failed']);
    }

    public static function withPercentage(Percentage $percentage, string $message, ?array $metadata = null): self
    {
        return new self($percentage, $message, $metadata);
    }

    public static function fromRatio(int $current, int $total, string $message, ?array $metadata = null): self
    {
        return new self(
            percentage: Percentage::fromRatio($current, $total),
            message: $message,
            metadata: $metadata
        );
    }

    public function isCompleted(): bool
    {
        return $this->percentage->isFull();
    }

    public function isFailed(): bool
    {
        return isset($this->metadata['status']) && $this->metadata['status'] === 'failed';
    }

    public function isStarting(): bool
    {
        return $this->percentage->isZero() && ! $this->isFailed();
    }

    public function withMetadata(array $metadata): self
    {
        return new self(
            percentage: $this->percentage,
            message: $this->message,
            metadata: array_merge($this->metadata ?? [], $metadata)
        );
    }

    public function withUpdatedProgress(Percentage $percentage, string $message): self
    {
        return new self(
            percentage: $percentage,
            message: $message,
            metadata: $this->metadata
        );
    }

    public function toArray(): array
    {
        return [
            'percentage' => $this->percentage->getValue(),
            'percentage_formatted' => $this->percentage->format(),
            'message' => $this->message,
            'metadata' => $this->metadata,
            'is_completed' => $this->isCompleted(),
            'is_failed' => $this->isFailed(),
            'is_starting' => $this->isStarting(),
        ];
    }

    private function validate(): void
    {
        if (empty(trim($this->message))) {
            throw new \InvalidArgumentException('Progress message cannot be empty');
        }
    }
}
