<?php

declare(strict_types=1);

namespace apexl\Io\modules\tabulator\Controllers;

use apexl\Io\dto\LoaderCondition;
use apexl\Io\includes\Controller;
use apexl\Io\interfaces\OutputManagerInterface;
use apexl\Io\modules\tabulator\Interfaces\HasTabulatorViewInterface;
use apexl\Io\modules\tabulator\Request\TabulatorAjaxRequest;
use Arrayy\Type\StringCollection;
use JsonException;
use Psr\Http\Message\ResponseInterface;
use function apexl\Io\assertInstanceOf;

final readonly class TabulatorAjaxController extends Controller
{
    /**
     * @param class-string<HasTabulatorViewInterface> $entityClass
     */
    public function __construct(
        private string $entityClass,
        OutputManagerInterface $output,
    ) {
        assertInstanceOf($entityClass, HasTabulatorViewInterface::class);
        parent::__construct($output);
    }

    /**
     * @throws JsonException
     */
    public function __invoke(
        TabulatorAjaxRequest $request,
        ResponseInterface $response,
    ): ResponseInterface {
        $entity = new $this->entityClass();
        $requestedFields = new StringCollection([$request->field()]);

        $params = $request->data();
        $primaryKey = $entity->getPrimaryKey();

        $conditions = [
            LoaderCondition::in(
                sprintf('%s.%s', $entity->getTableName(), $entity->getPrimaryKey()),
                $request->data()[$primaryKey]
            ),
        ];

        $data = $entity::findMultiple(
            conditions: $conditions,
            fields: $requestedFields,
        );

        $data = array_map(
            function (HasTabulatorViewInterface $entity) use ($requestedFields, $request): mixed {
                $tabulated = $entity->tabulate($requestedFields, false);
                return $tabulated[$request->field()] ?? null;
            },
            $data->toArray(),
        );

        $data = array_combine($params[$primaryKey], $data);

        return $this->json(
            $response,
            ['data' => $data]
        );
    }
}
