<?php

declare(strict_types=1);

namespace App\Framework\Search;

use App\Framework\Search\ValueObjects\DocumentData;
use App\Framework\Search\ValueObjects\DocumentMetadata;
use App\Framework\Search\ValueObjects\EntityId;
use App\Framework\Search\ValueObjects\EntityType;

/**
 * Represents a document to be indexed
 * Now uses Value Objects to eliminate primitive obsession
 */
final readonly class SearchDocument
{
    public readonly DocumentMetadata $metadata;

    public function __construct(
        public EntityId $id,
        public EntityType $entityType,
        public DocumentData $data,
        ?DocumentMetadata $metadata = null
    ) {
        $this->metadata = $metadata ?? DocumentMetadata::empty();
    }

    public function hasMetadata(): bool
    {
        return ! $this->metadata->isEmpty();
    }

    public function withMetadata(string $key, mixed $value): self
    {
        return new self(
            $this->id,
            $this->entityType,
            $this->data,
            $this->metadata->with($key, $value)
        );
    }

    public function withDocumentData(DocumentData $data): self
    {
        return new self(
            $this->id,
            $this->entityType,
            $data,
            $this->metadata
        );
    }

    public function withField(string $field, mixed $value): self
    {
        return new self(
            $this->id,
            $this->entityType,
            $this->data->with($field, $value),
            $this->metadata
        );
    }

    public function withoutField(string $field): self
    {
        return new self(
            $this->id,
            $this->entityType,
            $this->data->without($field),
            $this->metadata
        );
    }

    /**
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'id' => $this->id->toString(),
            'entity_type' => $this->entityType->toString(),
            'data' => $this->data->toArray(),
            'metadata' => $this->metadata->toArray(),
        ];
    }

    /**
     * Get the document as an array suitable for search engine indexing
     * @return array<string, mixed>
     */
    public function toIndexArray(): array
    {
        $indexData = $this->data->toArray();
        $indexData['_id'] = $this->id->toString();
        $indexData['_type'] = $this->entityType->toString();

        // Add metadata as non-searchable fields
        foreach ($this->metadata->toArray() as $key => $value) {
            $indexData["_meta_{$key}"] = $value;
        }

        return $indexData;
    }
}
