<?php

declare(strict_types=1);

namespace apexl\Io\services;

use apexl\Io\collections\LoaderConditionCollection;
use apexl\Io\dto\LoaderCondition;
use apexl\Io\includes\System;
use apexl\Io\interfaces\HasGeneralSearchInterface;
use apexl\Io\modules\tabulator\Services\TabulatorColumnFieldNameResolver;
use apexl\Io\modules\tabulator\Services\TabulatorFieldRenamer;
use apexl\Vault\enums\WhereCondition;
use apexl\Vault\enums\WhereType;

final readonly class GeneralSearchLoaderConditionCollectionBuilder
{
    private TabulatorColumnFieldNameResolver $tabulatorColumnFieldNameResolver;
    private LoaderConditionCollection $conditions;

    public function __construct(
        private TabulatorFieldRenamer $renamer,
        private HasGeneralSearchInterface $entity,
    ) {
        $this->conditions = new LoaderConditionCollection();
        $this->tabulatorColumnFieldNameResolver = System::makeRegisteredService(
            TabulatorColumnFieldNameResolver::class,
            [
                'entity' => $entity,
            ]
        );

    }

    public function build(string $term): LoaderConditionCollection
    {
        $terms = $this->splitTerms($term);
        $fields = $this->entity->generalSearchFields();

        foreach ($terms as $term) {
            $this->conditions->add($this->forTerm($term, $fields));
        }

        return $this->conditions;
    }

    private function splitTerms(string $term): array
    {
        return explode(' ', $term);
    }

    private function forTerm(string $term, array $fields): LoaderConditionCollection
    {
        $conditions = new LoaderConditionCollection();

        foreach ($fields as $field) {
            $field = $this->renamer->rename($field);

            if ($this->entity->isRelationField($field)) {
                $conditions->add(
                    $this->forRelationField(
                        $field,
                        $term,
                    )
                );
                continue;
            }

            $conditions->add($this->forNonRelationField($field, $term));
        }

        return $conditions;
    }

    private function forRelationField(string $field, string $term): LoaderCondition
    {
        $relation = $this->entity->relation(strstr($field, '__', true));

        return $relation->loaderConditionForField(
            substr(strstr($field, '__'), 2),
            WhereCondition::LIKE,
            $term,
            WhereType::OR
        );
    }

    private function forNonRelationField(string $field, string $term): LoaderCondition
    {

        $_field = $this->tabulatorColumnFieldNameResolver->resolve($field);
        return new LoaderCondition(
            $_field,
            WhereCondition::LIKE,
            $term,
            WhereType::OR,
        );

    }
}