<script setup>
import { ref, computed, watch } from 'vue'
import { Head, router } from '@inertiajs/vue3'
import AdminLayout from '@/Layouts/AdminLayout.vue'
import CodeEditor from '@/Components/CodeEditor.vue'
import {
    CommandLineIcon,
    MagnifyingGlassIcon,
    ArrowPathIcon,
    ClipboardDocumentIcon,
    CheckIcon,
    ChevronDownIcon,
    ChevronRightIcon,
    FunnelIcon,
} from '@heroicons/vue/24/outline'
import axios from 'axios'

const props = defineProps({
    endpoints: Array,
    recent: Array,
})

// ─── Endpoint browser ─────────────────────────────────────────────────────────
const search    = ref('')
const filterTag = ref('')
const filterMethod = ref('')

const allTags = computed(() => {
    const tags = new Set()
    for (const ep of props.endpoints) {
        for (const t of ep.tags ?? []) tags.add(t)
    }
    return [...tags].sort()
})

const methodColors = {
    GET:    'bg-emerald-100 text-emerald-800',
    POST:   'bg-violet-100 text-violet-800',
    PUT:    'bg-amber-100 text-amber-800',
    PATCH:  'bg-sky-100 text-sky-800',
    DELETE: 'bg-rose-100 text-rose-800',
}

const filteredEndpoints = computed(() => {
    let list = props.endpoints
    if (filterMethod.value) list = list.filter(e => e.method === filterMethod.value)
    if (filterTag.value)    list = list.filter(e => e.tags?.includes(filterTag.value))
    if (search.value) {
        const q = search.value.toLowerCase()
        list = list.filter(e =>
            e.path.toLowerCase().includes(q) ||
            e.summary?.toLowerCase().includes(q)
        )
    }
    return list
})

// ─── Request builder ──────────────────────────────────────────────────────────
const form = ref({
    method:    'GET',
    path:      '/api/v1/',
    params:    [{ key: '', value: '' }],
    headers:   [{ key: 'Accept', value: 'application/json' }],
    body:      '',
    use_token: '',
})

const executing = ref(false)
const result    = ref(null)
const resultOpen = ref(true)

const bodyMethods = ['POST', 'PUT', 'PATCH']
const showBody = computed(() => bodyMethods.includes(form.value.method))

function selectEndpoint(ep) {
    form.value.method = ep.method
    form.value.path   = ep.path
    form.value.body   = ''
    form.value.params = [{ key: '', value: '' }]
}

function addParam()  { form.value.params.push({ key: '', value: '' }) }
function addHeader() { form.value.headers.push({ key: '', value: '' }) }
function removeParam(i)  { form.value.params.splice(i, 1) }
function removeHeader(i) { form.value.headers.splice(i, 1) }

function asObject(arr) {
    const o = {}
    for (const r of arr) {
        if (r.key.trim()) o[r.key.trim()] = r.value
    }
    return o
}

async function execute() {
    executing.value = true
    result.value    = null
    try {
        const { data } = await axios.post(route('admin.api-tester.execute'), {
            method:    form.value.method,
            path:      form.value.path,
            params:    asObject(form.value.params),
            headers:   asObject(form.value.headers),
            body:      showBody.value ? (form.value.body || null) : null,
            use_token: form.value.use_token || null,
        })
        result.value    = data
        resultOpen.value = true
        // Refresh history
        router.reload({ only: ['recent'] })
    } catch (err) {
        result.value = { error: err.response?.data?.message ?? err.message }
    } finally {
        executing.value = false
    }
}

function rerun(req) {
    form.value.method = req.method
    form.value.path   = req.path
    form.value.body   = req.body ?? ''
    try {
        const p = typeof req.params === 'string' ? JSON.parse(req.params) : (req.params ?? {})
        form.value.params = Object.entries(p).map(([k, v]) => ({ key: k, value: v }))
        if (!form.value.params.length) form.value.params = [{ key: '', value: '' }]
        const h = typeof req.headers === 'string' ? JSON.parse(req.headers) : (req.headers ?? {})
        form.value.headers = Object.entries(h).map(([k, v]) => ({ key: k, value: v }))
        if (!form.value.headers.length) form.value.headers = [{ key: '', value: '' }]
    } catch {/* noop */}
}

function prettyJson(str) {
    try { return JSON.stringify(JSON.parse(str), null, 2) } catch { return str }
}

const methodBadge = (m) => methodColors[m] ?? 'bg-slate-100 text-slate-700'

function statusClass(code) {
    if (!code) return 'bg-slate-200 text-slate-700'
    if (code < 300) return 'bg-emerald-100 text-emerald-800'
    if (code < 400) return 'bg-amber-100 text-amber-800'
    return 'bg-rose-100 text-rose-800'
}

const copied = ref(null)
async function copyText(text, key) {
    await navigator.clipboard.writeText(text)
    copied.value = key
    setTimeout(() => { copied.value = null }, 1500)
}
</script>

<template>
    <Head title="API Tester" />
    <AdminLayout>
        <div class="space-y-4">
            <!-- Header -->
            <div class="flex items-center gap-3">
                <CommandLineIcon class="h-7 w-7 text-sky-500" />
                <div>
                    <h1 class="text-2xl font-bold text-slate-900 dark:text-slate-100">API Tester</h1>
                    <p class="text-sm text-slate-500 dark:text-slate-400">Panel API'sini doğrudan test et. OpenAPI endpoint listesinden seç veya manuel gir.</p>
                </div>
            </div>

            <!-- Split pane -->
            <div class="grid grid-cols-1 lg:grid-cols-3 gap-5">

                <!-- ══ Left: Endpoint browser ══ -->
                <div class="lg:col-span-1 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-xl flex flex-col" style="max-height: 76vh;">
                    <div class="p-3 border-b border-slate-200 dark:border-slate-700 space-y-2">
                        <div class="relative">
                            <MagnifyingGlassIcon class="h-4 w-4 absolute left-2.5 top-2.5 text-slate-400" />
                            <input v-model="search" type="text" placeholder="Endpoint ara…"
                                class="w-full rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 pl-8 pr-3 py-2 text-xs focus:outline-none focus:ring-2 focus:ring-sky-400" />
                        </div>
                        <div class="flex gap-2">
                            <select v-model="filterMethod"
                                class="flex-1 rounded border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-2 py-1.5 text-xs focus:outline-none focus:ring-1 focus:ring-sky-400">
                                <option value="">Tüm Metodlar</option>
                                <option v-for="m in ['GET','POST','PUT','PATCH','DELETE']" :key="m">{{ m }}</option>
                            </select>
                            <select v-model="filterTag"
                                class="flex-1 rounded border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-2 py-1.5 text-xs focus:outline-none focus:ring-1 focus:ring-sky-400">
                                <option value="">Tüm Etiketler</option>
                                <option v-for="t in allTags" :key="t">{{ t }}</option>
                            </select>
                        </div>
                    </div>

                    <div class="flex-1 overflow-y-auto divide-y divide-slate-100 dark:divide-slate-800">
                        <div v-if="!props.endpoints.length" class="p-4 text-xs text-slate-400 italic text-center">
                            public/docs/openapi.json bulunamadı. Endpoint listesi boş.
                        </div>
                        <div v-if="props.endpoints.length && !filteredEndpoints.length" class="p-4 text-xs text-slate-400 italic text-center">
                            Sonuç bulunamadı.
                        </div>
                        <button
                            v-for="ep in filteredEndpoints"
                            :key="ep.method + ep.path"
                            @click="selectEndpoint(ep)"
                            class="w-full flex items-start gap-2 px-3 py-2.5 hover:bg-sky-50 dark:hover:bg-sky-900/20 text-left transition-colors"
                        >
                            <span :class="['shrink-0 text-xs font-bold font-mono rounded px-1.5 py-0.5 mt-0.5', methodBadge(ep.method)]">{{ ep.method }}</span>
                            <div class="min-w-0">
                                <p class="text-xs font-mono text-slate-700 dark:text-slate-300 break-all">{{ ep.path }}</p>
                                <p v-if="ep.summary" class="text-xs text-slate-400 truncate">{{ ep.summary }}</p>
                            </div>
                        </button>
                    </div>

                    <div class="p-2 border-t border-slate-200 dark:border-slate-700 text-xs text-slate-400 text-right">
                        {{ filteredEndpoints.length }} / {{ props.endpoints.length }} endpoint
                    </div>
                </div>

                <!-- ══ Right: Request builder ══ -->
                <div class="lg:col-span-2 space-y-4">
                    <div class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-xl p-5 space-y-4">
                        <!-- Method + path -->
                        <div class="flex gap-2">
                            <select v-model="form.method"
                                class="rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm font-mono font-bold focus:outline-none focus:ring-2 focus:ring-sky-400">
                                <option v-for="m in ['GET','POST','PUT','PATCH','DELETE']" :key="m">{{ m }}</option>
                            </select>
                            <input v-model="form.path" type="text" placeholder="/api/v1/…"
                                class="flex-1 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-sky-400" />
                        </div>

                        <!-- Token -->
                        <div>
                            <label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">Bearer Token (opsiyonel)</label>
                            <input v-model="form.use_token" type="password" placeholder="API Token"
                                class="w-full rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-sky-400" />
                        </div>

                        <!-- Query params -->
                        <div>
                            <div class="flex items-center justify-between mb-2">
                                <label class="text-xs font-medium text-slate-500">Query Params</label>
                                <button @click="addParam" class="text-xs text-sky-600 hover:underline">+ Ekle</button>
                            </div>
                            <div v-for="(p, i) in form.params" :key="'p'+i" class="flex gap-2 mb-1">
                                <input v-model="p.key" placeholder="Key"
                                    class="flex-1 rounded border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-2 py-1.5 text-xs focus:outline-none focus:ring-1 focus:ring-sky-400" />
                                <input v-model="p.value" placeholder="Değer"
                                    class="flex-1 rounded border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-2 py-1.5 text-xs focus:outline-none focus:ring-1 focus:ring-sky-400" />
                                <button @click="removeParam(i)" class="text-slate-400 hover:text-rose-500">
                                    <span class="text-sm leading-none">×</span>
                                </button>
                            </div>
                        </div>

                        <!-- Headers -->
                        <div>
                            <div class="flex items-center justify-between mb-2">
                                <label class="text-xs font-medium text-slate-500">Headers</label>
                                <button @click="addHeader" class="text-xs text-sky-600 hover:underline">+ Ekle</button>
                            </div>
                            <div v-for="(h, i) in form.headers" :key="'h'+i" class="flex gap-2 mb-1">
                                <input v-model="h.key" placeholder="Header adı"
                                    class="flex-1 rounded border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-2 py-1.5 text-xs focus:outline-none focus:ring-1 focus:ring-sky-400" />
                                <input v-model="h.value" placeholder="Değer"
                                    class="flex-1 rounded border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-2 py-1.5 text-xs focus:outline-none focus:ring-1 focus:ring-sky-400" />
                                <button @click="removeHeader(i)" class="text-slate-400 hover:text-rose-500">
                                    <span class="text-sm leading-none">×</span>
                                </button>
                            </div>
                        </div>

                        <!-- Body (only for POST/PUT/PATCH) -->
                        <div v-if="showBody">
                            <label class="block text-xs font-medium text-slate-500 mb-1">Body (JSON)</label>
                            <CodeEditor v-model="form.body" filename="body.json" height="180px" />
                        </div>

                        <button @click="execute" :disabled="executing || !form.path"
                            class="inline-flex items-center gap-2 rounded-lg bg-sky-600 hover:bg-sky-700 disabled:opacity-60 text-white px-5 py-2.5 text-sm font-semibold transition-colors">
                            <ArrowPathIcon v-if="executing" class="h-4 w-4 animate-spin" />
                            <CommandLineIcon v-else class="h-4 w-4" />
                            {{ executing ? 'İstek gönderiliyor…' : 'Gönder' }}
                        </button>
                    </div>

                    <!-- Response viewer -->
                    <div v-if="result" class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden">
                        <button @click="resultOpen = !resultOpen"
                            class="w-full flex items-center justify-between px-5 py-3 text-sm font-semibold text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-800">
                            <span class="flex items-center gap-2">
                                <span :class="['rounded px-2 py-0.5 text-xs font-bold', statusClass(result.status_code)]">
                                    {{ result.status_code ?? 'ERR' }}
                                </span>
                                <span v-if="result.duration_ms" class="text-slate-400 text-xs">{{ result.duration_ms }} ms</span>
                            </span>
                            <ChevronDownIcon v-if="resultOpen" class="h-4 w-4" />
                            <ChevronRightIcon v-else class="h-4 w-4" />
                        </button>

                        <div v-if="resultOpen" class="border-t border-slate-200 dark:border-slate-700 p-5 space-y-4">
                            <div v-if="result.error" class="text-rose-600 text-sm font-mono bg-rose-50 dark:bg-rose-950/30 rounded p-3">
                                {{ result.error }}
                            </div>

                            <!-- Response headers -->
                            <div v-if="result.response_headers">
                                <p class="text-xs font-medium text-slate-500 mb-1">Yanıt Headers</p>
                                <div class="text-xs font-mono bg-slate-50 dark:bg-slate-800 rounded p-3 max-h-36 overflow-auto space-y-0.5">
                                    <div v-for="(val, key) in result.response_headers" :key="key">
                                        <span class="text-sky-600">{{ key }}</span>: {{ Array.isArray(val) ? val.join(', ') : val }}
                                    </div>
                                </div>
                            </div>

                            <!-- Response body -->
                            <div v-if="result.response_body !== undefined">
                                <div class="flex items-center justify-between mb-1">
                                    <p class="text-xs font-medium text-slate-500">Yanıt Body</p>
                                    <button @click="copyText(result.response_body, 'resp')" class="text-slate-400 hover:text-sky-600">
                                        <CheckIcon v-if="copied === 'resp'" class="h-4 w-4 text-emerald-500" />
                                        <ClipboardDocumentIcon v-else class="h-4 w-4" />
                                    </button>
                                </div>
                                <pre class="text-xs font-mono bg-slate-50 dark:bg-slate-800 rounded p-3 overflow-auto max-h-72 whitespace-pre-wrap">{{ prettyJson(result.response_body) }}</pre>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- ══ Request history ══ -->
            <div v-if="recent.length" class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-xl">
                <div class="px-5 py-3 border-b border-slate-200 dark:border-slate-700">
                    <h3 class="font-semibold text-sm text-slate-700 dark:text-slate-300">Son İstekler</h3>
                </div>
                <div class="overflow-x-auto">
                    <table class="w-full text-xs">
                        <thead>
                            <tr class="border-b border-slate-100 dark:border-slate-800 text-left text-slate-500">
                                <th class="px-4 py-2 font-medium">Metod</th>
                                <th class="px-4 py-2 font-medium">Path</th>
                                <th class="px-4 py-2 font-medium">Durum</th>
                                <th class="px-4 py-2 font-medium">Süre</th>
                                <th class="px-4 py-2 font-medium">Zaman</th>
                                <th class="px-4 py-2 font-medium"></th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-slate-50 dark:divide-slate-800">
                            <tr v-for="req in recent" :key="req.id" class="hover:bg-slate-50 dark:hover:bg-slate-800/50">
                                <td class="px-4 py-2">
                                    <span :class="['font-bold font-mono rounded px-1.5 py-0.5', methodBadge(req.method)]">{{ req.method }}</span>
                                </td>
                                <td class="px-4 py-2 font-mono text-slate-600 dark:text-slate-300 max-w-xs truncate">{{ req.path }}</td>
                                <td class="px-4 py-2">
                                    <span v-if="req.status_code" :class="['rounded px-1.5 py-0.5', statusClass(req.status_code)]">{{ req.status_code }}</span>
                                    <span v-else class="text-slate-400">—</span>
                                </td>
                                <td class="px-4 py-2 text-slate-500">{{ req.duration_ms ? req.duration_ms + ' ms' : '—' }}</td>
                                <td class="px-4 py-2 text-slate-400">{{ new Date(req.sent_at).toLocaleString('tr-TR') }}</td>
                                <td class="px-4 py-2">
                                    <button @click="rerun(req)" class="text-sky-600 hover:text-sky-800 font-medium">Tekrar çalıştır</button>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </AdminLayout>
</template>
