<?php

use function Livewire\Volt\{layout};
layout('components.layouts.cms');

use Flux\Flux;
use FluxCms\Core\Models\CmsSearchIndex;
use function Livewire\Volt\{state, computed, on};

state([
    'search' => '',
    'editingId' => null,
    'editLocale' => 'de',
    'itemId' => '',
    'route' => '',
    'routeParams' => '',
    'category' => '',
    'titleKey' => '',
    'titleFallback' => '',
    'descriptionKey' => '',
    'descriptionFallbackKey' => '',
    'descriptionFallbackText' => '',
    'keywords' => [],
    'newKeyword' => '',
    'isPublished' => true,
    'reindexing' => false,
]);

$items = computed(
    fn () => CmsSearchIndex::query()
        ->when($this->search, fn ($q) => $q->where('item_id', 'like', "%{$this->search}%")
            ->orWhere('route', 'like', "%{$this->search}%")
            ->orWhere('category', 'like', "%{$this->search}%"))
        ->ordered()
        ->get()
);

$startEdit = function (int $id) {
    $item = CmsSearchIndex::find($id);
    if (! $item) {
        return;
    }

    $this->editingId = $id;
    $this->itemId = $item->item_id;
    $this->route = $item->route;
    $this->routeParams = implode(', ', $item->route_params ?? []);
    $this->category = $item->getTranslation('category', $this->editLocale, false) ?? '';
    $this->titleKey = $item->title_key ?? '';
    $this->titleFallback = $item->getTranslation('title_fallback', $this->editLocale, false) ?? '';
    $this->descriptionKey = $item->description_key ?? '';
    $this->descriptionFallbackKey = $item->description_fallback_key ?? '';
    $this->descriptionFallbackText = $item->getTranslation('description_fallback_text', $this->editLocale, false) ?? '';
    $this->keywords = $item->getTranslation('keywords', $this->editLocale, false) ?? [];
    if (! is_array($this->keywords)) {
        $this->keywords = [];
    }
    $this->isPublished = $item->is_published;
    $this->newKeyword = '';
};

$switchLocale = function (string $locale) {
    if ($this->editingId) {
        $item = CmsSearchIndex::find($this->editingId);
        if ($item) {
            $this->editLocale = $locale;
            $this->category = $item->getTranslation('category', $locale, false) ?? '';
            $this->titleFallback = $item->getTranslation('title_fallback', $locale, false) ?? '';
            $this->descriptionFallbackText = $item->getTranslation('description_fallback_text', $locale, false) ?? '';
            $this->keywords = $item->getTranslation('keywords', $locale, false) ?? [];
            if (! is_array($this->keywords)) {
                $this->keywords = [];
            }
        }
    } else {
        $this->editLocale = $locale;
    }
};

$save = function () {
    $item = CmsSearchIndex::find($this->editingId);
    if (! $item) {
        return;
    }

    $item->item_id = $this->itemId;
    $item->route = $this->route;
    $item->route_params = array_values(array_filter(array_map('trim', explode(',', $this->routeParams))));
    $item->setTranslation('category', $this->editLocale, $this->category);

    $item->title_key = $this->titleKey ?: null;
    $item->setTranslation('title_fallback', $this->editLocale, $this->titleFallback ?: null);

    $item->description_key = $this->descriptionKey ?: null;
    $item->description_fallback_key = $this->descriptionFallbackKey ?: null;
    $item->setTranslation('description_fallback_text', $this->editLocale, $this->descriptionFallbackText ?: null);

    $cleanKeywords = array_values(array_filter($this->keywords, fn ($k) => is_string($k) && trim($k) !== ''));
    $item->setTranslation('keywords', $this->editLocale, $cleanKeywords);
    $item->is_published = $this->isPublished;
    $item->save();

    Flux::toast(variant: 'success', heading: 'Gespeichert', text: "Suchindex-Eintrag '{$item->item_id}' wurde gespeichert.");
};

$addKeyword = function () {
    $keyword = trim($this->newKeyword);
    if ($keyword !== '' && ! in_array($keyword, $this->keywords)) {
        $this->keywords[] = $keyword;
    }
    $this->newKeyword = '';
};

$removeKeyword = function (int $index) {
    unset($this->keywords[$index]);
    $this->keywords = array_values($this->keywords);
};

$create = function () {
    $maxOrder = CmsSearchIndex::max('order') ?? -1;
    $item = CmsSearchIndex::create([
        'item_id' => 'new-item-' . time(),
        'route' => 'home',
        'route_params' => [],
        'category' => ['de' => 'Neu', 'en' => 'New'],
        'keywords' => ['de' => [], 'en' => []],
        'is_published' => false,
        'order' => $maxOrder + 1,
    ]);

    $this->editingId = $item->id;
    $this->itemId = $item->item_id;
    $this->route = $item->route;
    $this->routeParams = '';
    $this->category = 'Neu';
    $this->titleKey = '';
    $this->titleFallback = '';
    $this->descriptionKey = '';
    $this->descriptionFallbackKey = '';
    $this->descriptionFallbackText = '';
    $this->keywords = [];
    $this->isPublished = false;
    $this->newKeyword = '';

    Flux::toast(variant: 'success', heading: 'Erstellt', text: 'Neuer Suchindex-Eintrag wurde erstellt.');
};

$delete = function (int $id) {
    $item = CmsSearchIndex::find($id);
    if ($item) {
        $name = $item->item_id;
        $item->delete();
        if ($this->editingId === $id) {
            $this->editingId = null;
        }
        Flux::toast(variant: 'success', heading: 'Geloescht', text: "Eintrag '{$name}' wurde entfernt.");
    }
};

$togglePublished = function (int $id) {
    $item = CmsSearchIndex::find($id);
    if ($item) {
        $item->is_published = ! $item->is_published;
        $item->save();
        Flux::toast(variant: 'success', heading: 'Status geaendert', text: $item->is_published ? 'Aktiviert' : 'Deaktiviert');
    }
};

$moveUp = function (int $id) {
    $item = CmsSearchIndex::find($id);
    if (! $item) {
        return;
    }
    $prev = CmsSearchIndex::where('order', '<', $item->order)->orderByDesc('order')->first();
    if ($prev) {
        $tmpOrder = $item->order;
        $item->order = $prev->order;
        $prev->order = $tmpOrder;
        $item->save();
        $prev->save();
    }
};

$moveDown = function (int $id) {
    $item = CmsSearchIndex::find($id);
    if (! $item) {
        return;
    }
    $next = CmsSearchIndex::where('order', '>', $item->order)->orderBy('order')->first();
    if ($next) {
        $tmpOrder = $item->order;
        $item->order = $next->order;
        $next->order = $tmpOrder;
        $item->save();
        $next->save();
    }
};

$reindex = function () {
    $this->reindexing = true;

    try {
        $exitCode = \Illuminate\Support\Facades\Artisan::call('search:extract-keywords', [
            '--apply' => true,
            '--locale' => ['de', 'en'],
        ]);

        $deItems = [];
        $enItems = [];
        $dePath = lang_path('de/search_index.php');
        $enPath = lang_path('en/search_index.php');

        if (file_exists($dePath)) {
            $deConfig = require $dePath;
            $deItems = collect($deConfig['items'] ?? [])->keyBy('id');
        }
        if (file_exists($enPath)) {
            $enConfig = require $enPath;
            $enItems = collect($enConfig['items'] ?? [])->keyBy('id');
        }

        $updated = 0;
        foreach (CmsSearchIndex::all() as $entry) {
            $de = $deItems->get($entry->item_id);
            $en = $enItems->get($entry->item_id);

            if ($de && ! empty($de['keywords'])) {
                $existing = $entry->getTranslation('keywords', 'de', false) ?? [];
                $merged = array_values(array_unique(array_merge(
                    is_array($existing) ? $existing : [],
                    $de['keywords']
                )));
                $entry->setTranslation('keywords', 'de', $merged);
            }

            if ($en && ! empty($en['keywords'])) {
                $existing = $entry->getTranslation('keywords', 'en', false) ?? [];
                $merged = array_values(array_unique(array_merge(
                    is_array($existing) ? $existing : [],
                    $en['keywords']
                )));
                $entry->setTranslation('keywords', 'en', $merged);
            }

            if ($entry->isDirty()) {
                $entry->save();
                $updated++;
            }
        }

        Flux::toast(variant: 'success', heading: 'Reindexierung abgeschlossen', text: "{$updated} Eintraege aktualisiert.");
    } catch (\Exception $e) {
        Flux::toast(variant: 'danger', heading: 'Fehler', text: $e->getMessage());
    }

    $this->reindexing = false;
};

?>

<div>
    <div class="mb-6 flex items-center justify-between">
        <div>
            <flux:heading size="xl">Suchindex</flux:heading>
            <flux:text class="mt-1">Verwalte die Seiten-Suche: Keywords, Kategorien und Beschreibungen.</flux:text>
        </div>
        <div class="flex gap-2">
            <flux:button wire:click="reindex" variant="ghost" icon="arrow-path" wire:loading.attr="disabled"
                wire:target="reindex">
                <span wire:loading.remove wire:target="reindex">Reindexieren</span>
                <span wire:loading wire:target="reindex">Wird reindexiert...</span>
            </flux:button>
            <flux:button wire:click="create" variant="primary" icon="plus">Neuer Eintrag</flux:button>
        </div>
    </div>

    <div class="mb-4">
        <flux:input wire:model.live.debounce.300ms="search" placeholder="Suche nach ID, Route oder Kategorie..."
            icon="magnifying-glass" />
    </div>

    <div class="flex gap-6">
        {{-- Liste --}}
        <div class="w-80 shrink-0 space-y-1 overflow-y-auto" style="max-height: 80vh;">
            @foreach ($this->items as $item)
                <div wire:key="si-{{ $item->id }}"
                    class="group flex cursor-pointer items-center gap-2 rounded-lg border px-3 py-2 transition
                        {{ $editingId === $item->id ? 'border-blue-500 bg-blue-50 dark:border-blue-400 dark:bg-blue-950' : 'border-zinc-200 hover:border-zinc-300 dark:border-zinc-700 dark:hover:border-zinc-600' }}
                        {{ ! $item->is_published ? 'opacity-50' : '' }}"
                    wire:click="startEdit({{ $item->id }})">
                    <div class="min-w-0 flex-1">
                        <p class="truncate text-sm font-medium text-zinc-800 dark:text-zinc-200">
                            {{ $item->item_id }}</p>
                        <p class="truncate text-xs text-zinc-400">
                            {{ $item->getTranslation('category', 'de', false) }}
                            &middot; {{ $item->route }}</p>
                    </div>
                    <div class="flex shrink-0 items-center gap-1">
                        <flux:button size="xs" variant="ghost" icon="chevron-up"
                            wire:click.stop="moveUp({{ $item->id }})" class="opacity-0 group-hover:opacity-100" />
                        <flux:button size="xs" variant="ghost" icon="chevron-down"
                            wire:click.stop="moveDown({{ $item->id }})" class="opacity-0 group-hover:opacity-100" />
                    </div>
                </div>
            @endforeach
        </div>

        {{-- Editor --}}
        <div class="flex-1">
            @if ($editingId)
                @php $currentItem = CmsSearchIndex::find($editingId); @endphp
                @if ($currentItem)
                    <div class="rounded-xl border border-zinc-200 bg-white p-6 dark:border-zinc-700 dark:bg-zinc-900">
                        <div class="mb-4 flex items-center justify-between">
                            <flux:heading size="lg">{{ $currentItem->item_id }}</flux:heading>
                            <div class="flex items-center gap-3">
                                <div class="flex gap-1">
                                    @foreach (config('flux-cms.locales', ['de' => 'DE', 'en' => 'EN']) as $code => $label)
                                        <flux:button size="xs"
                                            variant="{{ $editLocale === $code ? 'primary' : 'ghost' }}"
                                            wire:click="switchLocale('{{ $code }}')">
                                            {{ strtoupper($code) }}
                                        </flux:button>
                                    @endforeach
                                </div>
                                <flux:button size="sm" variant="{{ $isPublished ? 'primary' : 'ghost' }}"
                                    wire:click="togglePublished({{ $editingId }})">
                                    {{ $isPublished ? 'Aktiv' : 'Inaktiv' }}
                                </flux:button>
                                <flux:button size="sm" variant="danger" icon="trash"
                                    wire:click="delete({{ $editingId }})"
                                    wire:confirm="Suchindex-Eintrag wirklich loeschen?" />
                            </div>
                        </div>

                        <div class="grid grid-cols-2 gap-4">
                            <flux:input wire:model="itemId" label="Item-ID" placeholder="z.B. home, leistungen" />
                            <flux:input wire:model="route" label="Route (Named)" placeholder="z.B. home, leistungen" />
                        </div>

                        <div class="mt-4">
                            <flux:input wire:model="routeParams" label="Route-Parameter (kommagetrennt)"
                                placeholder="z.B. strategische-fmcg-projektrealisierung" />
                        </div>

                        <div class="mt-4 grid grid-cols-2 gap-4">
                            <flux:input wire:model="category"
                                label="Kategorie ({{ strtoupper($editLocale) }})"
                                placeholder="z.B. Startseite, Leistungen" />
                            <flux:input wire:model="titleKey" label="Title-Key (CMS)"
                                placeholder="z.B. welcome.title" />
                        </div>

                        <div class="mt-4 grid grid-cols-2 gap-4">
                            <flux:input wire:model="titleFallback"
                                label="Title-Fallback ({{ strtoupper($editLocale) }})"
                                placeholder="Fallback wenn kein Key" />
                            <flux:input wire:model="descriptionKey" label="Description-Key (CMS)"
                                placeholder="z.B. welcome.hero.description" />
                        </div>

                        <div class="mt-4 grid grid-cols-2 gap-4">
                            <flux:input wire:model="descriptionFallbackKey" label="Description-Fallback-Key"
                                placeholder="Optionaler Fallback-Key" />
                            <flux:input wire:model="descriptionFallbackText"
                                label="Description-Fallback ({{ strtoupper($editLocale) }})"
                                placeholder="Statischer Fallback-Text" />
                        </div>

                        {{-- Keywords --}}
                        <div class="mt-6">
                            <label class="mb-2 block text-sm font-medium">
                                Keywords ({{ strtoupper($editLocale) }})
                                <span class="text-zinc-400">- {{ count($keywords) }} Eintraege</span>
                            </label>

                            <div class="mb-3 flex flex-wrap gap-1.5">
                                @foreach ($keywords as $kIdx => $keyword)
                                    <span wire:key="kw-{{ $kIdx }}-{{ md5($keyword) }}"
                                        class="inline-flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-medium
                                            {{ str_contains($keyword, '.') ? 'bg-blue-50 text-blue-700 dark:bg-blue-950 dark:text-blue-300' : 'bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300' }}">
                                        @if (str_contains($keyword, '.'))
                                            <x-heroicon-s-key class="h-3 w-3 opacity-50" />
                                        @endif
                                        {{ $keyword }}
                                        <button wire:click="removeKeyword({{ $kIdx }})"
                                            class="ml-0.5 text-zinc-400 hover:text-red-500">
                                            <x-heroicon-s-x-mark class="h-3 w-3" />
                                        </button>
                                    </span>
                                @endforeach
                            </div>

                            <div class="flex gap-2">
                                <flux:input wire:model="newKeyword" placeholder="Neues Keyword oder CMS-Key..."
                                    wire:keydown.enter.prevent="addKeyword" class="flex-1!" />
                                <flux:button wire:click="addKeyword" icon="plus" size="sm">Hinzufuegen</flux:button>
                            </div>
                            <p class="mt-1 text-xs text-zinc-400">
                                <x-heroicon-s-key class="inline h-3 w-3 text-blue-500" /> = CMS-Key (wird aufgeloest),
                                normale Keywords werden direkt verwendet.
                                Enter druecken oder Button klicken zum Hinzufuegen.
                            </p>
                        </div>

                        {{-- Vorschau --}}
                        @php
                            $preview = $currentItem->toFrontendArray($editLocale);
                        @endphp
                        <div class="mt-6 rounded-lg border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-700 dark:bg-zinc-800">
                            <p class="mb-2 text-xs font-medium uppercase tracking-wide text-zinc-400">Vorschau
                                ({{ strtoupper($editLocale) }})</p>
                            <p class="text-xs text-zinc-400">{{ $preview['category'] }}</p>
                            <p class="text-sm font-semibold text-zinc-800 dark:text-zinc-200">
                                {{ $preview['title'] ?: '(kein Titel)' }}</p>
                            <p class="mt-0.5 line-clamp-2 text-xs text-zinc-500">
                                {{ $preview['description'] ?: '(keine Beschreibung)' }}</p>
                            @if (! empty($preview['url']))
                                <p class="mt-1 truncate text-xs text-blue-500">{{ $preview['url'] }}</p>
                            @endif
                            @if (! empty($preview['keywords']))
                                <div class="mt-2 flex flex-wrap gap-1">
                                    @foreach (array_slice($preview['keywords'], 0, 10) as $kw)
                                        <span
                                            class="rounded bg-zinc-200 px-1.5 py-0.5 text-[10px] text-zinc-600 dark:bg-zinc-700 dark:text-zinc-400">{{ $kw }}</span>
                                    @endforeach
                                    @if (count($preview['keywords']) > 10)
                                        <span
                                            class="rounded bg-zinc-200 px-1.5 py-0.5 text-[10px] text-zinc-600 dark:bg-zinc-700 dark:text-zinc-400">+{{ count($preview['keywords']) - 10 }}
                                            weitere</span>
                                    @endif
                                </div>
                            @endif
                        </div>

                        <div class="mt-4 flex justify-end">
                            <flux:button wire:click="save" variant="primary" icon="check">Speichern</flux:button>
                        </div>
                    </div>
                @endif
            @else
                <div class="flex h-64 items-center justify-center rounded-xl border border-dashed border-zinc-300 dark:border-zinc-700">
                    <div class="text-center">
                        <x-heroicon-o-magnifying-glass class="mx-auto h-10 w-10 text-zinc-300 dark:text-zinc-600" />
                        <p class="mt-2 text-sm text-zinc-400">Eintrag aus der Liste auswaehlen oder neuen erstellen.
                        </p>
                    </div>
                </div>
            @endif
        </div>
    </div>
</div>
