<?php
namespace boru\ai\Embedding;

class EmbeddingResult
{
    /** @var string|null */
    protected $provider;

    /** @var string|null */
    protected $model;

    /** @var array */
    protected $embeddings = array();

    /** @var array */
    protected $usage = array();

    /** @var array */
    protected $metadata = array();

    /** @var bool */
    protected $cacheHit = false;

    public function provider($value = null)
    {
        if ($value !== null) {
            $this->provider = (string)$value;
            return $this;
        }
        return $this->provider;
    }

    public function model($value = null)
    {
        if ($value !== null) {
            $this->model = (string)$value;
            return $this;
        }
        return $this->model;
    }

    public function embeddings(array $value = null)
    {
        if ($value !== null) {
            $this->embeddings = array_values($value);
            return $this;
        }
        return $this->embeddings;
    }

    public function addEmbedding(array $vector, $input = null, $index = null, array $metadata = array())
    {
        $item = array(
            'vector' => array_values($vector),
            'input' => $input,
            'index' => $index === null ? count($this->embeddings) : (int)$index,
            'metadata' => $metadata,
        );

        $this->embeddings[] = $item;
        return $this;
    }

    public function embedding($index = 0)
    {
        return isset($this->embeddings[$index]) ? $this->embeddings[$index] : null;
    }

    public function vector($index = 0)
    {
        $embedding = $this->embedding($index);
        if (!is_array($embedding) || !isset($embedding['vector']) || !is_array($embedding['vector'])) {
            return array();
        }
        return $embedding['vector'];
    }

    public function vectors()
    {
        $vectors = array();
        foreach ($this->embeddings as $embedding) {
            $vectors[] = isset($embedding['vector']) && is_array($embedding['vector']) ? $embedding['vector'] : array();
        }
        return $vectors;
    }

    public function usage(array $value = null)
    {
        if ($value !== null) {
            $this->usage = $value;
            return $this;
        }
        return $this->usage;
    }

    public function metadata($key = null, $value = null)
    {
        if ($key === null) {
            return $this->metadata;
        }

        if (is_array($key)) {
            $this->metadata = $key;
            return $this;
        }

        if (func_num_args() > 1) {
            $this->metadata[(string)$key] = $value;
            return $this;
        }

        return array_key_exists($key, $this->metadata) ? $this->metadata[$key] : null;
    }

    public function cacheHit($value = null)
    {
        if ($value !== null) {
            $this->cacheHit = $value ? true : false;
            return $this;
        }
        return $this->cacheHit ? true : false;
    }

    public function toArray()
    {
        return array(
            'provider' => $this->provider(),
            'model' => $this->model(),
            'embeddings' => $this->embeddings(),
            'usage' => $this->usage(),
            'metadata' => $this->metadata(),
            'cache_hit' => $this->cacheHit(),
        );
    }

    public static function fromArray(array $data)
    {
        $result = new self();
        if (isset($data['provider'])) {
            $result->provider($data['provider']);
        }
        if (isset($data['model'])) {
            $result->model($data['model']);
        }
        if (isset($data['embeddings']) && is_array($data['embeddings'])) {
            $result->embeddings($data['embeddings']);
        }
        if (isset($data['usage']) && is_array($data['usage'])) {
            $result->usage($data['usage']);
        }
        if (isset($data['metadata']) && is_array($data['metadata'])) {
            $result->metadata($data['metadata']);
        }
        if (isset($data['cache_hit'])) {
            $result->cacheHit($data['cache_hit'] ? true : false);
        }
        return $result;
    }
}
