<script setup>
import { ref, computed, watch, onBeforeUnmount } from 'vue'
import axios from 'axios'
import { debounce } from 'lodash'
import {
    MagnifyingGlassIcon, XMarkIcon, DocumentIcon, FolderIcon,
    AdjustmentsHorizontalIcon, BoltIcon,
} from '@heroicons/vue/24/outline'
import { formatBytes } from '@/Composables/useFileIcons'

/**
 * In-panel search: filename pattern + optional content grep.
 *
 * Performance:
 *   - 400ms debounce on input — typing doesn't fire a request per keystroke.
 *   - Min 3 characters before auto-search triggers (manual Enter overrides).
 *   - Previous in-flight request is cancelled via AbortController so the UI
 *     only ever reflects the latest query.
 *
 * Props:
 *   - show         v-model:show
 *   - basePath     start path (defaults to current)
 *
 * Emits:
 *   - update:show
 *   - navigate(path)   jump to result
 */
const props = defineProps({
    show: Boolean,
    basePath: { type: String, default: '' },
})

const emit = defineEmits(['update:show', 'navigate'])

const pattern = ref('')
const contentQuery = ref('')
const caseSensitive = ref(false)
const maxResults = ref(100)
const searching = ref(false)
const items = ref([])
const matches = ref([])
const lastError = ref(null)

const totalResults = computed(() => items.value.length + matches.value.length)

const minChars = 3
const tooShort = computed(() => {
    const longest = Math.max(pattern.value.length, contentQuery.value.length)
    return longest > 0 && longest < minChars
})

// In-flight request — cancelled when a new search starts.
let abortController = null

const performSearch = async (auto = false) => {
    // Manual searches (Enter / button) bypass the min-char guard so
    // users can still search single-char globs like "*".
    if (auto && tooShort.value) return

    if (!pattern.value && !contentQuery.value) {
        if (!auto) lastError.value = 'En az bir arama kriteri girin.'
        items.value = []
        matches.value = []
        return
    }

    // Cancel previous request before starting a new one.
    if (abortController) {
        try { abortController.abort() } catch { /* */ }
    }
    abortController = new AbortController()

    searching.value = true
    lastError.value = null
    try {
        const { data } = await axios.get(route('customer.files.search'), {
            params: {
                path: props.basePath || '',
                pattern: pattern.value || null,
                content: contentQuery.value || null,
                case_sensitive: caseSensitive.value ? 1 : 0,
                max_results: maxResults.value,
            },
            signal: abortController.signal,
        })
        items.value = data.items || data.files || []
        matches.value = data.matches || data.content_matches || []
    } catch (e) {
        // Cancelled — caller superseded by new query; don't disturb UI.
        if (e?.code === 'ERR_CANCELED' || e?.name === 'CanceledError') return
        lastError.value = e?.response?.data?.error ?? e.message
    } finally {
        searching.value = false
    }
}

// Debounced auto-search on input (400ms).
const debouncedSearch = debounce(() => performSearch(true), 400)

watch([pattern, contentQuery, caseSensitive], () => {
    if (!props.show) return
    if (tooShort.value) return
    debouncedSearch()
})

// Reset when modal opens.
watch(() => props.show, (open) => {
    if (open) {
        lastError.value = null
    } else {
        // Cancel any in-flight request when modal closes.
        try { abortController?.abort() } catch { /* */ }
    }
})

const navigateAndClose = (path) => {
    const parent = path.split('/').slice(0, -1).join('/')
    emit('navigate', parent)
    emit('update:show', false)
}

const handleKeydown = (e) => {
    if (e.key === 'Enter') {
        // Manual Enter — full search regardless of length.
        debouncedSearch.cancel?.()
        performSearch(false)
    }
    if (e.key === 'Escape') emit('update:show', false)
}

onBeforeUnmount(() => {
    debouncedSearch.cancel?.()
    try { abortController?.abort() } catch { /* */ }
})
</script>

<template>
    <Teleport to="body">
        <div v-if="show"
             class="fixed inset-0 z-50 flex items-start justify-center bg-slate-900/60 p-4 pt-20"
             @click.self="emit('update:show', false)">
            <div class="w-full max-w-3xl rounded-xl bg-white shadow-2xl dark:bg-slate-800">
                <!-- Header -->
                <div class="flex items-center justify-between border-b border-slate-200 p-4 dark:border-slate-700">
                    <h3 class="flex items-center gap-2 text-lg font-semibold text-slate-900 dark:text-slate-100">
                        <MagnifyingGlassIcon class="h-5 w-5 text-indigo-500" />
                        Dosya Ara
                        <span class="ml-2 text-xs font-mono text-slate-400">{{ basePath || '/' }}</span>
                        <span v-if="searching" class="ml-2 inline-flex items-center gap-1 text-xs text-indigo-500">
                            <span class="inline-block h-3 w-3 animate-spin rounded-full border-2 border-indigo-300 border-t-indigo-600"></span>
                            aranıyor
                        </span>
                    </h3>
                    <button @click="emit('update:show', false)"
                            class="rounded p-1 text-slate-400 hover:bg-slate-100 hover:text-slate-700 dark:hover:bg-slate-700">
                        <XMarkIcon class="h-5 w-5" />
                    </button>
                </div>

                <!-- Inputs -->
                <div class="space-y-3 border-b border-slate-200 p-4 dark:border-slate-700">
                    <div>
                        <label class="block text-xs font-medium uppercase text-slate-500 dark:text-slate-400">Dosya adı / yolu</label>
                        <input v-model="pattern" @keydown="handleKeydown"
                               type="text"
                               placeholder="*.php, backup-*, README"
                               class="mt-1 w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm dark:border-slate-600 dark:bg-slate-700 dark:text-slate-100"
                               autofocus />
                    </div>
                    <div>
                        <label class="block text-xs font-medium uppercase text-slate-500 dark:text-slate-400">İçerik (opsiyonel, grep)</label>
                        <input v-model="contentQuery" @keydown="handleKeydown"
                               type="text"
                               placeholder="DB_PASSWORD, function login"
                               class="mt-1 w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm dark:border-slate-600 dark:bg-slate-700 dark:text-slate-100" />
                    </div>
                    <div class="flex flex-wrap items-center gap-4 text-sm">
                        <label class="flex items-center gap-1.5 text-slate-600 dark:text-slate-300 cursor-pointer">
                            <input type="checkbox" v-model="caseSensitive" class="rounded border-slate-300 text-indigo-600" />
                            <span>Büyük/küçük harf duyarlı</span>
                        </label>
                        <label class="flex items-center gap-1.5 text-slate-600 dark:text-slate-300">
                            <AdjustmentsHorizontalIcon class="h-4 w-4" />
                            <span>Maks sonuç:</span>
                            <input v-model.number="maxResults" type="number" min="10" max="500"
                                   class="w-16 rounded border border-slate-300 px-2 py-0.5 text-xs dark:border-slate-600 dark:bg-slate-700" />
                        </label>
                        <span v-if="tooShort" class="text-xs text-amber-600">
                            En az {{ minChars }} karakter (veya Enter ile zorla)
                        </span>
                        <button @click="performSearch(false)" :disabled="searching"
                                class="ml-auto inline-flex items-center gap-1.5 rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 disabled:opacity-50">
                            <BoltIcon class="h-4 w-4" />
                            {{ searching ? 'Aranıyor…' : 'Ara' }}
                        </button>
                    </div>
                </div>

                <!-- Error -->
                <div v-if="lastError" class="border-b border-red-100 bg-red-50 px-4 py-2 text-sm text-red-700">
                    {{ lastError }}
                </div>

                <!-- Results -->
                <div class="max-h-96 overflow-y-auto p-2">
                    <p v-if="!searching && totalResults === 0 && (pattern || contentQuery) && !tooShort"
                       class="px-4 py-8 text-center text-sm text-slate-500">
                        Eşleşen sonuç yok.
                    </p>

                    <!-- Filename matches -->
                    <div v-if="items.length > 0">
                        <p class="px-3 py-1.5 text-[10px] font-semibold uppercase tracking-wide text-slate-500">
                            Dosya adı eşleşmeleri ({{ items.length }})
                        </p>
                        <ul class="space-y-0.5">
                            <li v-for="item in items" :key="item.path">
                                <button @click="navigateAndClose(item.path)"
                                        class="flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left hover:bg-slate-50 dark:hover:bg-slate-700/40">
                                    <FolderIcon v-if="item.type === 'dir'" class="h-4 w-4 text-amber-500" />
                                    <DocumentIcon v-else class="h-4 w-4 text-slate-400" />
                                    <div class="flex-1 min-w-0">
                                        <p class="truncate font-mono text-sm text-slate-700 dark:text-slate-200">{{ item.path }}</p>
                                        <p v-if="item.size != null" class="text-xs text-slate-500">{{ formatBytes(item.size) }}</p>
                                    </div>
                                </button>
                            </li>
                        </ul>
                    </div>

                    <!-- Content grep matches -->
                    <div v-if="matches.length > 0" class="mt-3">
                        <p class="px-3 py-1.5 text-[10px] font-semibold uppercase tracking-wide text-slate-500">
                            İçerik eşleşmeleri ({{ matches.length }})
                        </p>
                        <ul class="space-y-0.5">
                            <li v-for="(m, i) in matches" :key="i">
                                <button @click="navigateAndClose(m.path)"
                                        class="flex w-full flex-col rounded-lg px-3 py-2 text-left hover:bg-slate-50 dark:hover:bg-slate-700/40">
                                    <div class="flex items-baseline gap-2">
                                        <DocumentIcon class="h-3.5 w-3.5 text-slate-400" />
                                        <span class="font-mono text-xs text-indigo-600 dark:text-indigo-400">{{ m.path }}:{{ m.line }}</span>
                                    </div>
                                    <code class="mt-0.5 truncate text-xs text-slate-600 dark:text-slate-300">{{ m.snippet }}</code>
                                </button>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </Teleport>
</template>
