<?php
declare(strict_types=1);

namespace PpPhp\Core\Platform\Event\Sourcing\Domain;

final class DomainEventEnvelope
{
    public function __construct(
        private readonly string $envelopeId,
        private readonly string $eventId,
        private readonly string $eventType,
        private readonly string $aggregateId,
        private readonly string $aggregateType,
        private readonly int $sequence,
        private readonly array $payload = [],
        private readonly array $metadata = [],
        private readonly string $createdAt = ''
    ) {}

    public static function fromStoredEvent(array $event): self
    {
        $eventId = (string) ($event['eventId'] ?? '');
        return new self(
            'domain_env_' . substr(hash('sha256', $eventId . json_encode($event)), 0, 24),
            $eventId,
            (string) ($event['eventType'] ?? ''),
            (string) ($event['aggregateId'] ?? ''),
            (string) ($event['aggregateType'] ?? ''),
            (int) ($event['sequence'] ?? 0),
            (array) ($event['payload'] ?? []),
            (array) ($event['metadata'] ?? []),
            date('c')
        );
    }

    public static function fromArray(array $data): self
    {
        return new self(
            (string) ($data['envelopeId'] ?? ''),
            (string) ($data['eventId'] ?? ''),
            (string) ($data['eventType'] ?? ''),
            (string) ($data['aggregateId'] ?? ''),
            (string) ($data['aggregateType'] ?? ''),
            (int) ($data['sequence'] ?? 0),
            (array) ($data['payload'] ?? []),
            (array) ($data['metadata'] ?? []),
            (string) ($data['createdAt'] ?? '')
        );
    }

    public function envelopeId(): string { return $this->envelopeId; }
    public function eventId(): string { return $this->eventId; }
    public function eventType(): string { return $this->eventType; }
    public function aggregateType(): string { return $this->aggregateType; }
    public function sequence(): int { return max(0, $this->sequence); }

    public function toArray(): array
    {
        return [
            'envelopeId' => $this->envelopeId,
            'eventId' => $this->eventId,
            'eventType' => $this->eventType,
            'aggregateId' => $this->aggregateId,
            'aggregateType' => $this->aggregateType,
            'sequence' => $this->sequence(),
            'payload' => $this->payload,
            'metadata' => $this->metadata,
            'createdAt' => $this->createdAt !== '' ? $this->createdAt : date('c'),
        ];
    }
}
