<?php

declare(strict_types=1);

namespace Builder\Core\Http\Controllers\Resource;

use Builder\Core\Foundation\Contracts\Translatable;
use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Tables\Column;
use Builder\Core\Foundation\Tables\RowAction;
use Builder\Core\Http\Controllers\Concerns\HasColumnFormats;
use Builder\Core\Http\Controllers\Concerns\HasIndexQuery;
use Builder\Core\Http\Controllers\Concerns\HasResourceResolving;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

final class ResourceIndexController
{
    use HasColumnFormats;
    use HasIndexQuery;
    use HasResourceResolving;

    public function __construct(private readonly Registry $registry) {}

    public function __invoke(Request $request, string $resource): Response
    {
        $definition = $this->resolveOrFail($resource);
        $this->authorizeResource($request, $definition, 'index');

        $model = $definition->getModel();
        $modelInstance = new $model;
        $isTranslatable = $modelInstance instanceof Translatable;
        $locale = $isTranslatable ? $this->resolveContentLocale($request) : null;

        $query = $this->buildIndexQuery($request, $definition);

        $allowed = (array) config('builder.pagination.allowed', [10, 25, 50, 100]);
        $default = (int) config('builder.pagination.per_page', 25);
        $perPage = (int) $request->query('per_page', $default);

        if (! in_array($perPage, $allowed, true)) {
            $perPage = $default;
        }

        $records = $query->paginate($perPage)->withQueryString();

        $columns = $definition->getColumns();
        $rowActions = $definition->getRowActions();

        if ($definition->isDuplicatable()) {
            $prefix = (string) config('builder.prefix', 'admin');
            $slug = $definition->getSlug();
            $duplicateAction = RowAction::make('duplicate')
                ->label(__('builder::builder.resources.duplicate'))
                ->icon('copy')
                ->method('post')
                ->urlUsing(fn (array $record): string => "/{$prefix}/{$slug}/{$record['id']}/duplicate");
            $createPermission = $definition->resolvePermissionForAction('store');
            if ($createPermission !== null) {
                $duplicateAction->permission($createPermission);
            }

            $rowActions = [...$rowActions, $duplicateAction];
        }

        $hasRowActions = count($rowActions) > 0;
        $hasFormats = (bool) array_filter($columns, fn (Column $c): bool => $c->getFormat() !== null);

        $records = $records->through(function (mixed $item) use ($columns, $rowActions, $hasFormats, $hasRowActions, $locale, $definition): array {
            $data = $hasFormats
                ? $this->applyColumnFormats($item, $columns, $locale)
                : $item->toArray();

            if ($hasRowActions) {
                $data['_rowActions'] = array_map(fn (RowAction $a): array => $a->toArray($data), $rowActions);
            }

            $data['_canDelete'] = $this->canDeleteRecord($definition, $item);

            return $data;
        });

        return Inertia::render('Resource/Index', [
            'resource' => $definition->toArray(),
            'records' => $records,
            'currentLocale' => $locale,
            'availableLocales' => $isTranslatable ? $this->resolveAvailableLanguages() : [],
        ]);
    }
}
