<?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\Http\Controllers\Concerns\HasResourceResolving;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

final class ResourceOptionsController
{
    use HasResourceResolving;

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

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

        $model = $definition->getModel();
        $labelKey = (string) $request->query('label', 'name');
        $search = (string) $request->query('search', '');
        $locale = (string) $request->query('locale', '');

        $instance = new $model;

        $query = $model::query()->limit(50);

        if ($search !== '') {
            if ($instance instanceof Translatable && $locale !== '') {
                $baseTable = $instance->getTable();
                $translationTable = $instance->getTranslationTable();
                $foreignKey = $instance->getTranslationForeignKey();
                $primaryKey = $instance->getKeyName();
                $query->whereExists(function (QueryBuilder $sub) use ($baseTable, $translationTable, $foreignKey, $primaryKey, $labelKey, $locale, $search): void {
                    $sub->selectRaw('1')
                        ->from($translationTable)
                        ->whereColumn("{$translationTable}.{$foreignKey}", "{$baseTable}.{$primaryKey}")
                        ->where("{$translationTable}.locale", $locale)
                        ->where("{$translationTable}.{$labelKey}", 'like', "%{$search}%");
                });
            } else {
                $query->where($labelKey, 'like', "%{$search}%");
            }
        }

        $options = $query->get()->map(function (mixed $record) use ($labelKey, $locale): array {
            $label = null;
            $slug = null;

            if ($record instanceof Translatable && $locale !== '') {
                $translation = $record->getTranslation($locale);

                if ($translation !== null) {
                    $label = $translation->{$labelKey} ?? null;
                    $slug = $translation->getAttribute('slug');
                }
            }

            if ($label === null) {
                $label = $record->{$labelKey} ?? null;
            }

            if ($label === null && $record instanceof Translatable) {
                $translations = $record->getTranslations();

                if ($translations->isNotEmpty()) {
                    $fallback = $translations->first()->{$labelKey} ?? null;

                    if ($fallback !== null && $fallback !== '') {
                        $label = $fallback.' ('.__('builder::builder.untranslated').')';
                    }
                }
            }

            if ($slug === null) {
                $slug = $record->getAttribute('slug');
            }

            return [
                'id' => $record->getKey(),
                'label' => (string) ($label ?? $record->getKey()),
                'slug' => $slug,
            ];
        })->values()->all();

        return response()->json(['options' => $options]);
    }
}
