<?php

declare(strict_types=1);

namespace apexl\Io\modules\tabulator\Tabulatable\LoaderConditionCallback;

use apexl\Io\exceptions\LoaderConditionResolutionException;
use apexl\Io\exceptions\TabulatorFilterConditionCannotBeConvertedToWhereException;
use apexl\Io\interfaces\LoaderConditionInterface;
use apexl\Io\modules\tabulator\Collections\TabulatorFilterCollection;
use apexl\Io\modules\tabulator\Dto\TabulatorFilter;
use apexl\Io\modules\tabulator\Enums\TabulatorFilterCondition;
use apexl\Io\modules\tabulator\Interfaces\HasTabulatorViewInterface;
use apexl\Io\modules\tabulator\Interfaces\TabulatableLoaderConditionCallback;
use apexl\Io\modules\tabulator\Services\TabulatorFieldRenamer;

final readonly class CreatedLoaderConditionCallback implements TabulatableLoaderConditionCallback
{
    private string $dateField;
    private string $contactField;

    public function __construct(
        private HasTabulatorViewInterface $entity,
        TabulatorFieldRenamer $fieldRenamer,
        string $dateField = 'created',
        string $contactField = 'creator.name',
    ) {
        $this->contactField = $fieldRenamer->rename($contactField);
        $this->dateField = $fieldRenamer->rename($dateField);
    }

    /**
     * @throws LoaderConditionResolutionException
     * @throws TabulatorFilterConditionCannotBeConvertedToWhereException
     */
    public function __invoke(
        TabulatorFilter $filter,
    ): LoaderConditionInterface {
        $filters = new TabulatorFilterCollection();

        if ($filter->value['search'] ?? '') {
            $filters->append(
                new TabulatorFilter(
                    $this->dateField,
                    $filter->value['search'],
                    TabulatorFilterCondition::LIKE,
                    $this->entity
                        ->tabulatable()
                        ->column($this->dateField)
                        ->with('filterOn', $this->contactField)
                        ->without('loaderConditionCallback'),
                )
            );
        }

        $value = [];

        if ($filter->value['start'] ?? null) {
            $value['start'] = strtotime($filter->value['start']);
        }

        if ($filter->value['end'] ?? null) {
            $value['end'] = strtotime($filter->value['end']);
        }

        if ($value) {
            $filters->append(
                new TabulatorFilter(
                    $this->dateField,
                    $value,
                    TabulatorFilterCondition::BETWEEN,
                    $this->entity
                        ->tabulatable()
                        ->column($this->dateField)
                        ->with('filterOn', $this->dateField)
                        ->without('loaderConditionCallback'),

                )
            );
        }

        $conditions = $filters->toLoaderConditions($this->entity);

        $conditions->setShouldWrap(false);

        return $conditions;
    }
}
