<script lang="ts">
    import { Checkbox } from 'bits-ui'
    import { goto } from '$app/navigation'
    import { page } from '$app/state'

    export type TagFilterConfig = {
        type: 'tags'
        key: string
        label: string
        options: { label: string; value: string }[]
    }

    export type DateRangeFilterConfig = {
        type: 'date-range'
        keyFrom: string
        keyTo: string
        label: string
    }

    export type SelectFilterConfig = {
        type: 'select'
        key: string
        label: string
        options: { label: string; value: string }[]
    }

    export type FilterConfig = TagFilterConfig | DateRangeFilterConfig | SelectFilterConfig

    let { filters }: { filters: FilterConfig[] } = $props()

    // ── Read current URL state ────────────────────────────────────────────
    function getParam(key: string): string {
        return page.url.searchParams.get(key) ?? ''
    }

    function getParamArray(key: string): string[] {
        const val = page.url.searchParams.get(key)
        return val ? val.split(',').filter(Boolean) : []
    }

    // ── Local filter state (derived from URL) ─────────────────────────────
    let tagValues = $state<Record<string, string[]>>(
        Object.fromEntries(
            filters
                .filter((f): f is TagFilterConfig => f.type === 'tags')
                .map((f) => [f.key, getParamArray(f.key)])
        )
    )

    let excludeValues = $state<Record<string, string[]>>(
        Object.fromEntries(
            filters
                .filter((f): f is TagFilterConfig => f.type === 'tags')
                .map((f) => [f.key + '_exclude', getParamArray(f.key + '_exclude')])
        )
    )

    let dateValues = $state<Record<string, string>>(
        Object.fromEntries(
            filters
                .filter((f): f is DateRangeFilterConfig => f.type === 'date-range')
                .flatMap((f) => [
                    [f.keyFrom, getParam(f.keyFrom)],
                    [f.keyTo, getParam(f.keyTo)],
                ])
        )
    )

    let selectValues = $state<Record<string, string>>(
        Object.fromEntries(
            filters
                .filter((f): f is SelectFilterConfig => f.type === 'select')
                .map((f) => [f.key, getParam(f.key)])
        )
    )

    // ── Mobile drawer ─────────────────────────────────────────────────────
    let drawerOpen = $state(false)

    // ── Apply filters → navigate ──────────────────────────────────────────
    function apply() {
        const params = new URLSearchParams(page.url.searchParams)

        for (const [key, vals] of Object.entries(tagValues)) {
            if (vals.length) params.set(key, vals.join(','))
            else params.delete(key)
        }
        for (const [key, vals] of Object.entries(excludeValues)) {
            if (vals.length) params.set(key, vals.join(','))
            else params.delete(key)
        }
        for (const [key, val] of Object.entries(dateValues)) {
            if (val) params.set(key, val)
            else params.delete(key)
        }
        for (const [key, val] of Object.entries(selectValues)) {
            if (val) params.set(key, val)
            else params.delete(key)
        }

        params.delete('page') // reset pagination on filter change
        goto(`?${params.toString()}`, { keepFocus: true })
        drawerOpen = false
    }

    function reset() {
        for (const key of Object.keys(tagValues)) tagValues[key] = []
        for (const key of Object.keys(excludeValues)) excludeValues[key] = []
        for (const key of Object.keys(dateValues)) dateValues[key] = ''
        for (const key of Object.keys(selectValues)) selectValues[key] = ''
        goto(page.url.pathname, { keepFocus: true })
        drawerOpen = false
    }

    const hasActiveFilters = $derived(
        Object.values(tagValues).some((v) => v.length) ||
        Object.values(excludeValues).some((v) => v.length) ||
        Object.values(dateValues).some((v) => v) ||
        Object.values(selectValues).some((v) => v)
    )
</script>

<!-- ── Mobile trigger ──────────────────────────────────────────────────── -->
<div class="lg:hidden mb-4">
    <button
            onclick={() => drawerOpen = true}
            class="flex items-center gap-2 px-4 py-2 border border-gray-300 rounded text-sm hover:bg-gray-50 transition"
    >
        <svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor">
            <path fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h6a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h3a1 1 0 110 2H4a1 1 0 01-1-1z" clip-rule="evenodd" />
        </svg>
        Filter
        {#if hasActiveFilters}
            <span class="inline-flex items-center justify-center w-4 h-4 text-xs bg-brand text-white rounded-full">
                {Object.values(tagValues).flat().length + Object.values(excludeValues).flat().length + Object.values(selectValues).filter(Boolean).length}
            </span>
        {/if}
    </button>
</div>

<!-- ── Mobile drawer backdrop ─────────────────────────────────────────── -->
{#if drawerOpen}
    <button
            class="fixed inset-0 z-30 bg-black/40 lg:hidden"
            onclick={() => drawerOpen = false}
            aria-label="Filter schließen"
    ></button>
    <div class="fixed inset-y-0 left-0 z-40 w-80 bg-white shadow-xl p-6 overflow-y-auto lg:hidden">
        <div class="flex items-center justify-between mb-6">
            <h2 class="font-semibold text-lg">Filter</h2>
            <button onclick={() => drawerOpen = false} class="text-gray-400 hover:text-gray-600">✕</button>
        </div>
        <svelte:self {filters} />
    </div>
{/if}

<!-- ── Desktop aside (rendered by parent layout) ─────────────────────── -->
<aside class="hidden lg:block w-56 shrink-0">
    <div class="sticky top-24 flex flex-col gap-6">
        {@render filterContent()}
    </div>
</aside>

<!-- ── Filter content (shared mobile/desktop) ────────────────────────── -->
{#snippet filterContent()}
    {#each filters as filter}
        {#if filter.type === 'tags'}
            <div>
                <h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 mb-3">{filter.label}</h3>

                <!-- Include -->
                <Checkbox.Group bind:value={tagValues[filter.key]} class="flex flex-col gap-2">
                    {#each filter.options as opt}
                        <div class="flex items-center gap-2">
                            <Checkbox.Root
                                    value={opt.value}
                                    class="w-4 h-4 rounded border border-gray-300 data-[state=checked]:bg-brand data-[state=checked]:border-brand transition flex items-center justify-center"
                            >
                                {#snippet children({ checked })}
                                    {#if checked}
                                        <svg class="w-2.5 h-2.5 text-white" viewBox="0 0 10 10" fill="none">
                                            <path d="M1.5 5l2.5 2.5 4.5-4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
                                        </svg>
                                    {/if}
                                {/snippet}
                            </Checkbox.Root>
                            <label class="text-sm text-gray-700 cursor-pointer">{opt.label}</label>
                        </div>
                    {/each}
                </Checkbox.Group>

                <!-- Exclude -->
                {#if tagValues[filter.key + '_exclude'] !== undefined}
                    <div class="mt-3 pt-3 border-t border-gray-100">
                        <p class="text-xs text-gray-400 mb-2">Ausschließen</p>
                        <Checkbox.Group bind:value={excludeValues[filter.key + '_exclude']} class="flex flex-col gap-2">
                            {#each filter.options as opt}
                                <div class="flex items-center gap-2">
                                    <Checkbox.Root
                                            value={opt.value}
                                            class="w-4 h-4 rounded border border-gray-300 data-[state=checked]:bg-red-500 data-[state=checked]:border-red-500 transition flex items-center justify-center"
                                    >
                                        {#snippet children({ checked })}
                                            {#if checked}
                                                <svg class="w-2.5 h-2.5 text-white" viewBox="0 0 10 10" fill="none">
                                                    <path d="M2 2l6 6M8 2l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                                                </svg>
                                            {/if}
                                        {/snippet}
                                    </Checkbox.Root>
                                    <label class="text-sm text-gray-700 cursor-pointer">{opt.label}</label>
                                </div>
                            {/each}
                        </Checkbox.Group>
                    </div>
                {/if}
            </div>

        {:else if filter.type === 'date-range'}
            <div>
                <h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 mb-3">{filter.label}</h3>
                <div class="flex flex-col gap-2">
                    <div>
                        <label class="text-xs text-gray-500 mb-1 block">Von</label>
                        <input
                                type="number"
                                min="1600"
                                max="2100"
                                placeholder="z.B. 1900"
                                bind:value={dateValues[filter.keyFrom]}
                                class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:outline-none focus:border-brand"
                        />
                    </div>
                    <div>
                        <label class="text-xs text-gray-500 mb-1 block">Bis</label>
                        <input
                                type="number"
                                min="1600"
                                max="2100"
                                placeholder="z.B. 2024"
                                bind:value={dateValues[filter.keyTo]}
                                class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:outline-none focus:border-brand"
                        />
                    </div>
                </div>
            </div>

        {:else if filter.type === 'select'}
            <div>
                <h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 mb-3">{filter.label}</h3>
                <select
                        bind:value={selectValues[filter.key]}
                        class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded focus:outline-none focus:border-brand bg-white"
                >
                    <option value="">Alle</option>
                    {#each filter.options as opt}
                        <option value={opt.value}>{opt.label}</option>
                    {/each}
                </select>
            </div>
        {/if}
    {/each}

    <!-- Actions -->
    <div class="flex flex-col gap-2 pt-2">
        <button
                onclick={apply}
                class="w-full px-4 py-2 bg-brand text-white text-sm rounded hover:bg-brand/90 transition"
        >
            Anwenden
        </button>
        {#if hasActiveFilters}
            <button
                    onclick={reset}
                    class="w-full px-4 py-2 text-sm text-gray-500 hover:text-gray-700 transition"
            >
                Zurücksetzen
            </button>
        {/if}
    </div>
{/snippet}