<?php

namespace MintyPHP\Http\Input;

final class FormErrors
{
    /** @var array<string, array<int, string>> */
    private array $errors = [];

    public function add(string $field, string $message): self
    {
        $field = trim($field);
        if ($field === '') {
            $field = 'input';
        }

        $message = trim($message);
        if ($message === '') {
            return $this;
        }

        $this->errors[$field] ??= [];
        $this->errors[$field][] = $message;

        return $this;
    }

    /**
     * @param array<int, string> $messages
     */
    public function addMany(string $field, array $messages): self
    {
        foreach ($messages as $message) {
            $this->add($field, (string) $message);
        }

        return $this;
    }

    public function addGlobal(string $message): self
    {
        return $this->add('input', $message);
    }

    /**
     * @param array<string, array<int, string>|string>|array<int, string>|self $errors
     */
    public function merge(array|self $errors): self
    {
        if ($errors instanceof self) {
            $errors = $errors->toArray();
        }

        if (array_is_list($errors)) {
            foreach ($errors as $message) {
                $this->addGlobal((string) $message);
            }

            return $this;
        }

        foreach ($errors as $field => $messages) {
            if (is_array($messages)) {
                $this->addMany((string) $field, array_values(array_map('strval', $messages)));
                continue;
            }

            $this->add((string) $field, (string) $messages);
        }

        return $this;
    }

    public function hasAny(): bool
    {
        return $this->errors !== [];
    }

    /**
     * @return array<string, array<int, string>>
     */
    public function toArray(): array
    {
        return $this->errors;
    }

    /**
     * @return array<int, string>
     */
    public function toFlatList(): array
    {
        $flat = [];
        foreach ($this->errors as $messages) {
            foreach ($messages as $message) {
                $flat[] = $message;
            }
        }

        return $flat;
    }
}
