<script setup>
import { ref, computed } from 'vue'
import { Head, useForm, router } from '@inertiajs/vue3'
import AdminLayout from '@/Layouts/AdminLayout.vue'
import {
    ShieldCheckIcon,
    ChartBarIcon,
    Cog6ToothIcon,
    DocumentTextIcon,
    NoSymbolIcon,
    ShieldExclamationIcon,
    CodeBracketIcon,
    BeakerIcon,
    ArrowPathIcon,
    PlusIcon,
    TrashIcon,
    InformationCircleIcon,
    MagnifyingGlassIcon,
    CheckCircleIcon,
    XCircleIcon,
    BoltIcon,
    SparklesIcon,
    ExclamationTriangleIcon,
    PresentationChartLineIcon,
    PuzzlePieceIcon,
    EyeIcon,
    GlobeAltIcon,
    ArrowTopRightOnSquareIcon,
} from '@heroicons/vue/24/outline'
import axios from 'axios'
import { useConfirm } from '@/composables/useConfirm'
import { useCountryFlag } from '@/composables/useCountryFlag'

const { ask } = useConfirm()
const { flagUrl, countryName } = useCountryFlag()

const props = defineProps({
    settings: Object,
    exclusions: Array,
    whitelist: Array,
    custom_rules: Array,
    audit_events: Array,
    crs_history: Array,
    rulesets: Array,
    severities: Array,
    engine_modes: Array,
    stats: Object,
    rules_catalog: Array,
    crs_info: Object,
})

const activeTab = ref('dashboard')
const tabs = [
    { key: 'dashboard',  label: 'Genel Bakış',   icon: ChartBarIcon },
    { key: 'reports',    label: 'Raporlar',      icon: PresentationChartLineIcon, badge: 'YENİ' },
    { key: 'settings',   label: 'Ayarlar',       icon: Cog6ToothIcon },
    { key: 'rules',      label: 'Kurallar',      icon: DocumentTextIcon },
    { key: 'exclusions', label: 'İstisnalar',    icon: NoSymbolIcon },
    { key: 'audit',      label: 'Audit Log',     icon: ShieldExclamationIcon },
    { key: 'whitelist',  label: 'IP Whitelist',  icon: ShieldCheckIcon },
    { key: 'custom',     label: 'Özel Kurallar', icon: CodeBracketIcon },
    { key: 'vendors',    label: 'Vendor\'lar',   icon: PuzzlePieceIcon, badge: 'YENİ' },
    { key: 'crs',        label: 'CRS Update',    icon: SparklesIcon },
    { key: 'test',       label: 'Test Aracı',    icon: BeakerIcon },
]

// ── Engine status badge ────────────────────────────────────────────────────
const engineMode = computed(() => props.settings.engine_mode || (props.settings.engine_enabled === '1' ? 'on' : 'off'))
const engineBadge = computed(() => {
    const map = {
        on: { color: 'bg-emerald-500/15 text-emerald-300 ring-emerald-400/30', label: 'Aktif (Block)' },
        detection_only: { color: 'bg-amber-500/15 text-amber-300 ring-amber-400/30', label: 'Sadece İzle' },
        off: { color: 'bg-red-500/15 text-red-300 ring-red-400/30', label: 'Kapalı' },
    }
    return map[engineMode.value] || map.off
})

// ── Settings form (genişletilmiş) ─────────────────────────────────────────
const settingsForm = useForm({
    engine_mode: props.settings.engine_mode ?? 'on',
    audit_log_enabled: props.settings.audit_log_enabled === '1',
    audit_log_parts: props.settings.audit_log_parts ?? 'ABIJDEFHZ',
    active_ruleset: props.settings.active_ruleset ?? 'OWASP-CRS-3.3',
    paranoia_level: parseInt(props.settings.paranoia_level ?? '2'),
    request_body_access: props.settings.request_body_access === '1',
    response_body_access: props.settings.response_body_access === '1',
    request_body_limit: parseInt(props.settings.request_body_limit ?? '13107200'),
    request_body_nofiles_limit: parseInt(props.settings.request_body_nofiles_limit ?? '131072'),
    default_action: props.settings.default_action ?? 'deny',
    anomaly_threshold_inbound: parseInt(props.settings.anomaly_threshold_inbound ?? '5'),
    anomaly_threshold_outbound: parseInt(props.settings.anomaly_threshold_outbound ?? '4'),
    auto_exclude_wordpress: props.settings.auto_exclude_wordpress === '1',
    auto_exclude_drupal: props.settings.auto_exclude_drupal === '1',
    auto_exclude_joomla: props.settings.auto_exclude_joomla === '1',
})

const saveSettings = () => {
    settingsForm.patch(route('admin.modsecurity.settings.update'), { preserveScroll: true })
}

const paranoiaLabel = computed(() => ({
    1: 'Düşük (önerilen)', 2: 'Orta', 3: 'Yüksek', 4: 'Maksimum',
}[settingsForm.paranoia_level] || ''))

// ── Exclusion form ───────────────────────────────────────────────────────
const exclusionForm = useForm({ rule_id: '', domain_name: '', reason: '' })
const addExclusion = () => exclusionForm.post(route('admin.modsecurity.exclusions.store'), {
    preserveScroll: true,
    onSuccess: () => exclusionForm.reset(),
})
const removeExclusion = async (id) => {
    const ok = await ask({ title: 'İstisnayı Sil', message: 'Bu istisna kaldırılsın mı?', variant: 'danger', confirmText: 'Sil', cancelText: 'İptal' })
    if (!ok) return
    router.delete(route('admin.modsecurity.exclusions.destroy', id), { preserveScroll: true })
}
const quickExcludeFromAudit = (auditEventId) => {
    router.post(route('admin.modsecurity.exclusions.from_audit', auditEventId), {}, { preserveScroll: true })
}

// ── Whitelist form ───────────────────────────────────────────────────────
const whitelistForm = useForm({ ip_or_cidr: '', domain_name: '', label: '', reason: '' })
const addWhitelist = () => whitelistForm.post(route('admin.modsecurity.whitelist.store'), {
    preserveScroll: true,
    onSuccess: () => whitelistForm.reset(),
})
const removeWhitelist = async (id, ip) => {
    const ok = await ask({ title: 'Whitelist\'ten Kaldır', message: `${ip} silinecek. Bu IP artık ModSecurity kurallarından geçecek.`, variant: 'danger', confirmText: 'Sil', cancelText: 'İptal' })
    if (!ok) return
    router.delete(route('admin.modsecurity.whitelist.destroy', id), { preserveScroll: true })
}

// ── Custom rules form ────────────────────────────────────────────────────
const customRuleForm = useForm({
    name: '', description: '', rule_content: '',
    category: 'custom', domain_name: '', is_enabled: true,
})
const addCustomRule = () => customRuleForm.post(route('admin.modsecurity.custom_rules.store'), {
    preserveScroll: true,
    onSuccess: () => customRuleForm.reset(),
})
const toggleCustomRule = (id) => router.post(route('admin.modsecurity.custom_rules.toggle', id), {}, { preserveScroll: true })
const removeCustomRule = async (id, name) => {
    const ok = await ask({ title: 'Özel Kuralı Sil', message: `'${name}' kuralı kaldırılacak. Devam?`, variant: 'danger', confirmText: 'Sil', cancelText: 'İptal' })
    if (!ok) return
    router.delete(route('admin.modsecurity.custom_rules.destroy', id), { preserveScroll: true })
}

// ── Audit log search ─────────────────────────────────────────────────────
const auditFilter = ref({
    q: '', rule_id: '', source_ip: '', domain: '', severity: '', from: '', to: '', page: 1,
})
const auditResults = ref({ results: props.audit_events || [], total: (props.audit_events || []).length, page: 1 })
const auditSearching = ref(false)

const searchAudit = async () => {
    auditSearching.value = true
    try {
        const { data } = await axios.post(route('admin.modsecurity.audit.search'), auditFilter.value)
        if (data.success) {
            auditResults.value = data
        }
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        auditSearching.value = false
    }
}

const auditRefreshing = ref(false)
const refreshAudit = async () => {
    auditRefreshing.value = true
    try {
        const { data } = await axios.post(route('admin.modsecurity.audit.refresh'))
        if (data.success) {
            window.$toast?.success?.(`${data.inserted}/${data.total_fetched} yeni olay senkronize edildi`)
            router.reload({ only: ['audit_events', 'stats'], preserveScroll: true })
        }
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        auditRefreshing.value = false
    }
}

// ── Test request ─────────────────────────────────────────────────────────
const testForm = ref({
    method: 'GET',
    uri: "/admin?id=1' OR 1=1--",
    headers: 'User-Agent: Mozilla/5.0',
    body: '',
})
const testResult = ref(null)
const testRunning = ref(false)

const runTest = async () => {
    testRunning.value = true
    testResult.value = null
    try {
        const { data } = await axios.post(route('admin.modsecurity.test_request'), testForm.value)
        if (data.success) {
            testResult.value = data
        }
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        testRunning.value = false
    }
}

// ── CRS update ───────────────────────────────────────────────────────────
const crsUpdating = ref(false)
const updateCrs = async () => {
    const ok = await ask({ title: 'CRS Güncelleme', message: `OWASP CRS ${props.crs_info?.installed} → ${props.crs_info?.latest} sürümüne yükseltilecek. 3-5 dk sürebilir. Devam?`, variant: 'warning', confirmText: 'Güncelle', cancelText: 'İptal' })
    if (!ok) return

    crsUpdating.value = true
    try {
        const { data } = await axios.post(route('admin.modsecurity.crs.update'), {})
        if (data.success) {
            window.$toast?.success?.(`CRS ${data.from_version} → ${data.to_version} (${data.rules_count} kural)`)
            router.reload({ preserveScroll: true })
        }
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        crsUpdating.value = false
    }
}

// ── Rules catalog filter ─────────────────────────────────────────────────
const rulesFilter = ref({ q: '', category: '', severity: '' })
const filteredRules = computed(() => {
    let list = props.rules_catalog || []
    const q = rulesFilter.value.q.trim().toLowerCase()
    if (q) list = list.filter(r => r.rule_id.includes(q) || (r.description || '').toLowerCase().includes(q) || (r.tag || '').toLowerCase().includes(q))
    if (rulesFilter.value.category) list = list.filter(r => r.category === rulesFilter.value.category)
    if (rulesFilter.value.severity) list = list.filter(r => r.severity === rulesFilter.value.severity)
    return list.slice(0, 200)
})

const rulesCategories = computed(() => [...new Set((props.rules_catalog || []).map(r => r.category))])

// ── Helpers ──────────────────────────────────────────────────────────────
const formatTime = (val) => val ? new Date(val).toLocaleString('tr-TR') : '—'
const formatNumber = (n) => (n || 0).toLocaleString('tr-TR')
const formatBytes = (b) => {
    if (b < 1024) return b + ' B'
    if (b < 1048576) return (b / 1024).toFixed(1) + ' KB'
    if (b < 1073741824) return (b / 1048576).toFixed(1) + ' MB'
    return (b / 1073741824).toFixed(1) + ' GB'
}

const severityBadge = (sev) => ({
    CRITICAL: 'bg-red-100 text-red-700 ring-red-300',
    ERROR: 'bg-orange-100 text-orange-700 ring-orange-300',
    WARNING: 'bg-amber-100 text-amber-700 ring-amber-300',
    NOTICE: 'bg-sky-100 text-sky-700 ring-sky-300',
    INFO: 'bg-slate-100 text-slate-700 ring-slate-300',
}[sev] || 'bg-slate-100 text-slate-700 ring-slate-300')

const maxHourlyHits = computed(() => Math.max(1, ...(props.stats?.hourly_chart || []).map(h => h.hits || h.blocks || 0)))

// ── Rule Detail Modal ────────────────────────────────────────────────────
const ruleDetailOpen = ref(false)
const ruleDetail = ref(null)
const ruleDetailLoading = ref(false)
const openRuleDetail = async (ruleId) => {
    ruleDetailOpen.value = true
    ruleDetail.value = null
    ruleDetailLoading.value = true
    try {
        const { data } = await axios.get(route('admin.modsecurity.rules.detail', ruleId))
        if (data.success) ruleDetail.value = data
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        ruleDetailLoading.value = false
    }
}
const toggleRuleFromDetail = (ruleId) => {
    router.post(route('admin.modsecurity.rules.toggle', ruleId), {}, {
        preserveScroll: true,
        onSuccess: () => { ruleDetailOpen.value = false }
    })
}

// ── Event Detail Modal ───────────────────────────────────────────────────
const eventDetailOpen = ref(false)
const eventDetail = ref(null)
const eventDetailLoading = ref(false)
const openEventDetail = async (eventId) => {
    eventDetailOpen.value = true
    eventDetail.value = null
    eventDetailLoading.value = true
    try {
        const { data } = await axios.get(route('admin.modsecurity.audit.detail', eventId))
        if (data.success) eventDetail.value = data
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        eventDetailLoading.value = false
    }
}

// ── Reports tab data ─────────────────────────────────────────────────────
const reports = ref(null)
const reportsLoading = ref(false)
const loadReports = async () => {
    if (reports.value || reportsLoading.value) return
    reportsLoading.value = true
    try {
        const { data } = await axios.get(route('admin.modsecurity.reports'))
        if (data.success) reports.value = data
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        reportsLoading.value = false
    }
}

// ── Vendors tab data ─────────────────────────────────────────────────────
const vendors = ref(null)
const vendorsLoading = ref(false)
const loadVendors = async () => {
    if (vendors.value || vendorsLoading.value) return
    vendorsLoading.value = true
    try {
        const { data } = await axios.get(route('admin.modsecurity.vendors.list'))
        if (data.success) vendors.value = data.vendors
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        vendorsLoading.value = false
    }
}

const installVendor = async (vendor) => {
    const ok = await ask({
        title: 'Vendor Kurulumu',
        message: `${vendor.name} ruleset'i indirilecek (${vendor.source_url}). 1-3 dakika sürebilir. Devam?`,
        variant: 'primary', confirmText: 'Kur', cancelText: 'İptal',
    })
    if (!ok) return

    try {
        const { data } = await axios.post(route('admin.modsecurity.vendors.install'), {
            slug: vendor.slug, source_url: vendor.source_url,
        })
        if (data.success) {
            window.$toast?.success?.(`${vendor.name} kuruldu — ${data.rules_count} kural`)
            vendors.value = null
            loadVendors()
        }
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    }
}

const removeVendor = async (slug, name) => {
    const ok = await ask({
        title: 'Vendor Kaldır',
        message: `${name} ruleset'i kaldırılacak. Apache reload edilecek. Devam?`,
        variant: 'danger', confirmText: 'Kaldır', cancelText: 'İptal',
    })
    if (!ok) return
    router.delete(route('admin.modsecurity.vendors.remove', slug), {
        preserveScroll: true,
        onSuccess: () => { vendors.value = null; loadVendors() }
    })
}

// Auto-load data when tab becomes active
import { watch } from 'vue'
watch(activeTab, (tab) => {
    if (tab === 'reports') loadReports()
    if (tab === 'vendors') loadVendors()
})

// ── Country aggregate (Dashboard map) — DB'den top_countries ─────────────
// Stats objesinde varsa kullan, yoksa audit_events'ten hesapla (UI-side fallback)
const topCountries = computed(() => {
    if (props.stats?.top_countries?.length) return props.stats.top_countries
    if (!props.audit_events?.length) return []
    const counts = {}
    props.audit_events.forEach(e => {
        if (e.country_code) counts[e.country_code] = (counts[e.country_code] || 0) + 1
    })
    return Object.entries(counts)
        .map(([country_code, attacks]) => ({ country_code, attacks }))
        .sort((a, b) => b.attacks - a.attacks)
        .slice(0, 10)
})
const maxCountryAttacks = computed(() => Math.max(1, ...topCountries.value.map(c => c.attacks)))
</script>

<template>
    <Head title="ModSecurity (WAF) — Gelişmiş" />
    <AdminLayout>
        <template #header>
            <span class="flex items-center gap-2">
                <ShieldCheckIcon class="h-5 w-5 text-indigo-600" />
                ModSecurity / WAF — Gelişmiş Yönetim
                <span :class="['rounded-full px-2 py-0.5 text-xs font-semibold ring-1', engineBadge.color]">
                    {{ engineBadge.label }}
                </span>
            </span>
        </template>

        <!-- Tab bar -->
        <div class="mb-6 flex gap-1 rounded-xl border border-slate-200 bg-white p-1.5 shadow-sm overflow-x-auto">
            <button v-for="tab in tabs" :key="tab.key" @click="activeTab = tab.key"
                    :class="['flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition whitespace-nowrap',
                        activeTab === tab.key ? 'bg-indigo-600 text-white shadow' : 'text-slate-600 hover:bg-slate-50']">
                <component :is="tab.icon" class="h-4 w-4" />
                {{ tab.label }}
                <span v-if="tab.badge" class="inline-flex items-center rounded-full bg-amber-100 px-1.5 py-0.5 text-[9px] font-bold text-amber-700 leading-none">
                    {{ tab.badge }}
                </span>
            </button>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 1 — Dashboard
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'dashboard'" class="space-y-6">

            <!-- Stat cards -->
            <div class="grid grid-cols-2 lg:grid-cols-4 gap-4">
                <div class="rounded-xl border border-red-200 bg-gradient-to-br from-red-50 to-red-100 p-5">
                    <p class="text-xs uppercase font-medium text-red-700 mb-1">Son 24 Saat</p>
                    <p class="text-3xl font-bold text-red-900">{{ formatNumber(stats?.blocks_24h) }}</p>
                    <p class="text-xs text-red-600 mt-1">Engellenen istek</p>
                </div>
                <div class="rounded-xl border border-amber-200 bg-gradient-to-br from-amber-50 to-amber-100 p-5">
                    <p class="text-xs uppercase font-medium text-amber-700 mb-1">7 Gün</p>
                    <p class="text-3xl font-bold text-amber-900">{{ formatNumber(stats?.blocks_7d) }}</p>
                    <p class="text-xs text-amber-600 mt-1">Toplam blok</p>
                </div>
                <div class="rounded-xl border border-indigo-200 bg-gradient-to-br from-indigo-50 to-indigo-100 p-5">
                    <p class="text-xs uppercase font-medium text-indigo-700 mb-1">30 Gün</p>
                    <p class="text-3xl font-bold text-indigo-900">{{ formatNumber(stats?.blocks_30d) }}</p>
                    <p class="text-xs text-indigo-600 mt-1">Toplam blok</p>
                </div>
                <div class="rounded-xl border border-purple-200 bg-gradient-to-br from-purple-50 to-purple-100 p-5">
                    <p class="text-xs uppercase font-medium text-purple-700 mb-1">Benzersiz IP (24h)</p>
                    <p class="text-3xl font-bold text-purple-900">{{ formatNumber(stats?.unique_ips_24h) }}</p>
                    <p class="text-xs text-purple-600 mt-1">Farklı kaynak</p>
                </div>
            </div>

            <!-- Hourly chart -->
            <div class="rounded-xl border border-slate-200 bg-white shadow-sm p-5">
                <div class="flex items-center gap-2 mb-4">
                    <BoltIcon class="h-5 w-5 text-indigo-500" />
                    <h3 class="text-base font-semibold">Saatlik Saldırı Dağılımı (24h)</h3>
                </div>
                <div v-if="!stats?.hourly_chart || stats.hourly_chart.length === 0" class="py-8 text-center text-sm text-slate-500">
                    Henüz veri yok. "Audit Log" sekmesinden "Yenile" tıklayın.
                </div>
                <div v-else class="flex items-end justify-between gap-1 h-40">
                    <div v-for="h in stats.hourly_chart" :key="h.hour" class="flex-1 flex flex-col items-center gap-1 group">
                        <span class="text-[10px] font-bold text-slate-700 opacity-0 group-hover:opacity-100">{{ h.hits || h.blocks || 0 }}</span>
                        <div :style="{ height: `${((h.hits || h.blocks || 0) / maxHourlyHits) * 100}%`, minHeight: '2px' }"
                             class="w-full bg-gradient-to-t from-red-600/70 to-rose-500 rounded-t transition" :title="`${h.hour}: ${h.hits || h.blocks || 0} blok`"></div>
                        <span class="text-[9px] text-slate-500">{{ h.hour }}</span>
                    </div>
                </div>
            </div>

            <!-- Geographic attack map (top countries) -->
            <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                <div class="border-b border-slate-200 px-5 py-3 flex items-center gap-2">
                    <GlobeAltIcon class="h-5 w-5 text-indigo-500" />
                    <h3 class="text-base font-semibold">Coğrafi Saldırı Dağılımı</h3>
                    <span class="ml-auto text-xs text-slate-500">Son 7 gün</span>
                </div>
                <div v-if="!topCountries.length" class="px-5 py-12 text-center text-sm text-slate-500">
                    Henüz coğrafi veri yok. Audit log'tan senkronize edin.
                </div>
                <div v-else class="p-5 grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-3">
                    <div v-for="(c, i) in topCountries" :key="c.country_code" class="flex items-center gap-3">
                        <span class="text-slate-400 w-5 text-xs font-mono">{{ i + 1 }}</span>
                        <img :src="flagUrl(c.country_code)" :alt="c.country_code" class="w-8 h-6 rounded-sm ring-1 ring-slate-200 object-cover flex-shrink-0" loading="lazy" />
                        <span class="font-mono text-xs w-7">{{ c.country_code }}</span>
                        <span class="text-xs flex-shrink-0 w-24 truncate">{{ countryName(c.country_code) }}</span>
                        <div class="flex-1 h-4 bg-slate-100 rounded-full overflow-hidden">
                            <div :style="{ width: `${(c.attacks / maxCountryAttacks) * 100}%` }"
                                 class="h-full bg-gradient-to-r from-rose-500 to-red-600"></div>
                        </div>
                        <span class="font-mono font-bold text-red-600 text-xs w-16 text-right">{{ formatNumber(c.attacks) }}</span>
                    </div>
                </div>
            </div>

            <!-- Top tables -->
            <div class="grid grid-cols-1 lg:grid-cols-3 gap-4">

                <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                    <div class="border-b border-slate-200 px-5 py-3 flex items-center gap-2">
                        <ShieldExclamationIcon class="h-5 w-5 text-red-500" />
                        <h3 class="text-sm font-semibold">Top 10 Saldırgan IP</h3>
                    </div>
                    <div v-if="!stats?.top_ips || stats.top_ips.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">Veri yok.</div>
                    <table v-else class="min-w-full text-xs">
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="(item, i) in stats.top_ips" :key="i">
                                <td class="px-4 py-2 text-slate-400 w-6">{{ i + 1 }}</td>
                                <td class="px-4 py-2 font-mono">{{ item.ip }}</td>
                                <td class="px-4 py-2 text-right font-bold text-red-600">{{ formatNumber(item.hits) }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>

                <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                    <div class="border-b border-slate-200 px-5 py-3 flex items-center gap-2">
                        <DocumentTextIcon class="h-5 w-5 text-amber-500" />
                        <h3 class="text-sm font-semibold">Top Tetiklenen Kurallar</h3>
                    </div>
                    <div v-if="!stats?.top_rules || stats.top_rules.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">Veri yok.</div>
                    <table v-else class="min-w-full text-xs">
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="(item, i) in stats.top_rules" :key="i">
                                <td class="px-4 py-2 text-slate-400 w-6">{{ i + 1 }}</td>
                                <td class="px-4 py-2 font-mono font-bold text-amber-700">{{ item.rule_id }}</td>
                                <td class="px-4 py-2 text-right font-bold">{{ formatNumber(item.hits) }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>

                <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                    <div class="border-b border-slate-200 px-5 py-3 flex items-center gap-2">
                        <ChartBarIcon class="h-5 w-5 text-purple-500" />
                        <h3 class="text-sm font-semibold">Saldırı Kategorisi</h3>
                    </div>
                    <div v-if="!stats?.top_categories || stats.top_categories.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">Veri yok.</div>
                    <table v-else class="min-w-full text-xs">
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="(item, i) in stats.top_categories" :key="i">
                                <td class="px-4 py-2 text-slate-400 w-6">{{ i + 1 }}</td>
                                <td class="px-4 py-2 truncate">{{ item.category }}</td>
                                <td class="px-4 py-2 text-right font-bold text-purple-700">{{ formatNumber(item.hits) }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 2 — Ayarlar
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'settings'" class="space-y-6">

            <form @submit.prevent="saveSettings" class="space-y-6">

                <!-- Engine mode -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                    <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">Engine Modu</h3></div>
                    <div class="p-5 grid grid-cols-1 md:grid-cols-3 gap-4">
                        <label v-for="mode in engine_modes" :key="mode"
                               :class="['cursor-pointer rounded-xl border-2 p-4 transition',
                                   settingsForm.engine_mode === mode ? 'border-indigo-500 bg-indigo-50' : 'border-slate-200 hover:border-slate-300']">
                            <input type="radio" v-model="settingsForm.engine_mode" :value="mode" class="sr-only" />
                            <div class="flex items-center justify-between mb-2">
                                <span class="font-semibold text-sm">
                                    {{ mode === 'on' ? 'Aktif' : mode === 'detection_only' ? 'Sadece İzle' : 'Kapalı' }}
                                </span>
                                <CheckCircleIcon v-if="settingsForm.engine_mode === mode" class="h-5 w-5 text-indigo-500" />
                            </div>
                            <p class="text-xs text-slate-600">
                                {{ mode === 'on' ? 'Saldırı tespit edilirse blok' : mode === 'detection_only' ? 'Tespit eder ama bloklamaz (audit log)' : 'Tamamen devre dışı' }}
                            </p>
                        </label>
                    </div>
                </div>

                <!-- Ruleset + Paranoia -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                    <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">Kural Seti</h3></div>
                    <div class="p-5 grid grid-cols-1 md:grid-cols-2 gap-4">
                        <div>
                            <label class="block text-xs font-medium text-slate-700 mb-1">Aktif Ruleset</label>
                            <select v-model="settingsForm.active_ruleset" class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm">
                                <option v-for="rs in rulesets" :key="rs" :value="rs">{{ rs }}</option>
                            </select>
                        </div>
                        <div>
                            <label class="block text-xs font-medium text-slate-700 mb-1">Paranoia Seviyesi — <span class="text-indigo-600 font-bold">{{ settingsForm.paranoia_level }} · {{ paranoiaLabel }}</span></label>
                            <input v-model.number="settingsForm.paranoia_level" type="range" min="1" max="4" step="1" class="w-full accent-indigo-600 mt-2" />
                            <div class="flex justify-between text-[10px] text-slate-400 mt-1">
                                <span>1 Düşük</span><span>2</span><span>3</span><span>4 Max</span>
                            </div>
                        </div>
                        <div>
                            <label class="block text-xs font-medium text-slate-700 mb-1">Anomaly Threshold Inbound</label>
                            <input v-model.number="settingsForm.anomaly_threshold_inbound" type="number" min="1" class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                        </div>
                        <div>
                            <label class="block text-xs font-medium text-slate-700 mb-1">Anomaly Threshold Outbound</label>
                            <input v-model.number="settingsForm.anomaly_threshold_outbound" type="number" min="1" class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                        </div>
                        <div>
                            <label class="block text-xs font-medium text-slate-700 mb-1">Default Action</label>
                            <select v-model="settingsForm.default_action" class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm">
                                <option value="deny">deny (403)</option><option value="drop">drop (TCP RST)</option>
                                <option value="block">block</option><option value="redirect">redirect</option>
                            </select>
                        </div>
                    </div>
                </div>

                <!-- Auto exclusions -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                    <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">CMS Auto-Exclusions (yaygın false positive'ler için)</h3></div>
                    <div class="divide-y divide-slate-100">
                        <label class="flex items-center justify-between px-5 py-4 cursor-pointer hover:bg-slate-50">
                            <div><div class="font-medium text-sm">WordPress</div><p class="text-xs text-slate-500">wp-admin, wp-json, xmlrpc için tipik kural istisnalarını otomatik uygula</p></div>
                            <button type="button" @click="settingsForm.auto_exclude_wordpress = !settingsForm.auto_exclude_wordpress"
                                    :class="['relative inline-flex h-6 w-11 items-center rounded-full transition', settingsForm.auto_exclude_wordpress ? 'bg-indigo-600' : 'bg-slate-300']">
                                <span :class="['inline-block h-4 w-4 transform rounded-full bg-white transition', settingsForm.auto_exclude_wordpress ? 'translate-x-6' : 'translate-x-1']"></span>
                            </button>
                        </label>
                        <label class="flex items-center justify-between px-5 py-4 cursor-pointer hover:bg-slate-50">
                            <div><div class="font-medium text-sm">Drupal</div><p class="text-xs text-slate-500">Drupal admin, ajax, services için</p></div>
                            <button type="button" @click="settingsForm.auto_exclude_drupal = !settingsForm.auto_exclude_drupal"
                                    :class="['relative inline-flex h-6 w-11 items-center rounded-full transition', settingsForm.auto_exclude_drupal ? 'bg-indigo-600' : 'bg-slate-300']">
                                <span :class="['inline-block h-4 w-4 transform rounded-full bg-white transition', settingsForm.auto_exclude_drupal ? 'translate-x-6' : 'translate-x-1']"></span>
                            </button>
                        </label>
                        <label class="flex items-center justify-between px-5 py-4 cursor-pointer hover:bg-slate-50">
                            <div><div class="font-medium text-sm">Joomla</div><p class="text-xs text-slate-500">Joomla administrator, com_ paths için</p></div>
                            <button type="button" @click="settingsForm.auto_exclude_joomla = !settingsForm.auto_exclude_joomla"
                                    :class="['relative inline-flex h-6 w-11 items-center rounded-full transition', settingsForm.auto_exclude_joomla ? 'bg-indigo-600' : 'bg-slate-300']">
                                <span :class="['inline-block h-4 w-4 transform rounded-full bg-white transition', settingsForm.auto_exclude_joomla ? 'translate-x-6' : 'translate-x-1']"></span>
                            </button>
                        </label>
                    </div>
                </div>

                <!-- Audit + Body -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                    <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">Audit & Request Body</h3></div>
                    <div class="p-5 space-y-4">
                        <label class="flex items-center justify-between cursor-pointer">
                            <div><div class="font-medium text-sm">Audit Log</div><p class="text-xs text-slate-500">Tetiklenen kuralları modsec_audit.log'a yaz</p></div>
                            <button type="button" @click="settingsForm.audit_log_enabled = !settingsForm.audit_log_enabled"
                                    :class="['relative inline-flex h-6 w-11 items-center rounded-full transition', settingsForm.audit_log_enabled ? 'bg-indigo-600' : 'bg-slate-300']">
                                <span :class="['inline-block h-4 w-4 transform rounded-full bg-white transition', settingsForm.audit_log_enabled ? 'translate-x-6' : 'translate-x-1']"></span>
                            </button>
                        </label>
                        <div>
                            <label class="block text-xs font-medium text-slate-700 mb-1">Audit Log Parts (ABIJDEFHZ)</label>
                            <input v-model="settingsForm.audit_log_parts" class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                            <p class="text-[10px] text-slate-500 mt-1">A=audit header, B=request header, I=request body, J=files, D=intermediate response, E=intermediate body, F=final response, H=audit trailer, Z=audit footer</p>
                        </div>
                        <div class="grid grid-cols-2 gap-3">
                            <label class="flex items-center justify-between cursor-pointer rounded-lg ring-1 ring-slate-200 px-3 py-2">
                                <span class="text-xs font-medium">Request Body Erişimi</span>
                                <button type="button" @click="settingsForm.request_body_access = !settingsForm.request_body_access"
                                        :class="['relative inline-flex h-5 w-9 items-center rounded-full transition', settingsForm.request_body_access ? 'bg-emerald-600' : 'bg-slate-300']">
                                    <span :class="['inline-block h-3.5 w-3.5 transform rounded-full bg-white transition', settingsForm.request_body_access ? 'translate-x-5' : 'translate-x-1']"></span>
                                </button>
                            </label>
                            <label class="flex items-center justify-between cursor-pointer rounded-lg ring-1 ring-slate-200 px-3 py-2">
                                <span class="text-xs font-medium">Response Body Erişimi</span>
                                <button type="button" @click="settingsForm.response_body_access = !settingsForm.response_body_access"
                                        :class="['relative inline-flex h-5 w-9 items-center rounded-full transition', settingsForm.response_body_access ? 'bg-emerald-600' : 'bg-slate-300']">
                                    <span :class="['inline-block h-3.5 w-3.5 transform rounded-full bg-white transition', settingsForm.response_body_access ? 'translate-x-5' : 'translate-x-1']"></span>
                                </button>
                            </label>
                        </div>
                        <div class="grid grid-cols-2 gap-3">
                            <div>
                                <label class="block text-xs font-medium text-slate-700 mb-1">Request Body Limit (bytes)</label>
                                <input v-model.number="settingsForm.request_body_limit" type="number" class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                                <p class="text-[10px] text-slate-500 mt-0.5">{{ formatBytes(settingsForm.request_body_limit) }}</p>
                            </div>
                            <div>
                                <label class="block text-xs font-medium text-slate-700 mb-1">No-Files Body Limit (bytes)</label>
                                <input v-model.number="settingsForm.request_body_nofiles_limit" type="number" class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                                <p class="text-[10px] text-slate-500 mt-0.5">{{ formatBytes(settingsForm.request_body_nofiles_limit) }}</p>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="flex justify-end rounded-xl border border-slate-200 bg-white p-3 shadow-sm">
                    <button type="submit" :disabled="settingsForm.processing"
                            class="inline-flex items-center gap-2 rounded-lg bg-indigo-600 px-6 py-2 text-sm font-semibold text-white hover:bg-indigo-700 disabled:opacity-50">
                        <CheckCircleIcon class="h-5 w-5" />
                        {{ settingsForm.processing ? 'Kaydediliyor...' : 'Kaydet ve Apache Reload' }}
                    </button>
                </div>
            </form>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 3 — Kurallar Kataloğu
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'rules'" class="space-y-6">
            <div class="rounded-xl border border-indigo-200 bg-indigo-50 p-4 text-sm text-indigo-900 flex gap-3">
                <InformationCircleIcon class="h-5 w-5 flex-shrink-0 text-indigo-600" />
                <div>
                    <strong>Kural Kataloğu:</strong> Aktif CRS sürümünüzdeki tüm kuralları listeler. Belirli bir kuralı arayıp false positive bilgisi için ID'sini kopyalayabilirsiniz.
                </div>
            </div>

            <div class="grid grid-cols-1 md:grid-cols-4 gap-3">
                <div class="md:col-span-2 relative">
                    <MagnifyingGlassIcon class="absolute left-3 top-2.5 h-4 w-4 text-slate-400" />
                    <input v-model="rulesFilter.q" placeholder="Kural ID, açıklama veya tag ara..." class="w-full rounded-lg border border-slate-300 pl-9 pr-3 py-2 text-sm" />
                </div>
                <select v-model="rulesFilter.category" class="rounded-lg border border-slate-300 px-3 py-2 text-sm">
                    <option value="">Tüm kategoriler</option>
                    <option v-for="c in rulesCategories" :key="c" :value="c">{{ c }}</option>
                </select>
                <select v-model="rulesFilter.severity" class="rounded-lg border border-slate-300 px-3 py-2 text-sm">
                    <option value="">Tüm seviyeler</option>
                    <option v-for="s in severities" :key="s" :value="s">{{ s }}</option>
                </select>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                <div class="border-b border-slate-200 px-5 py-3">
                    <h3 class="text-base font-semibold">{{ filteredRules.length }} kural gösteriliyor (toplam {{ rules_catalog?.length || 0 }})</h3>
                </div>
                <div v-if="filteredRules.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">
                    Eşleşen kural yok.
                </div>
                <table v-else class="min-w-full text-sm">
                    <thead class="bg-slate-50 text-xs uppercase text-slate-500">
                        <tr>
                            <th class="px-4 py-2 text-left">Rule ID</th>
                            <th class="px-4 py-2 text-left">Kategori</th>
                            <th class="px-4 py-2 text-left">Tag</th>
                            <th class="px-4 py-2 text-left">Severity</th>
                            <th class="px-4 py-2 text-left">Açıklama</th>
                            <th class="px-4 py-2 text-left">Aksiyon</th>
                        </tr>
                    </thead>
                    <tbody class="divide-y divide-slate-100">
                        <tr v-for="r in filteredRules" :key="r.rule_id" class="hover:bg-slate-50">
                            <td class="px-4 py-2">
                                <button @click="openRuleDetail(r.rule_id)"
                                        class="font-mono font-bold text-indigo-600 hover:text-indigo-800 hover:underline">
                                    {{ r.rule_id }}
                                </button>
                            </td>
                            <td class="px-4 py-2 text-xs">{{ r.category }}</td>
                            <td class="px-4 py-2 font-mono text-[10px] text-slate-500">{{ r.tag }}</td>
                            <td class="px-4 py-2"><span :class="['inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium ring-1', severityBadge(r.severity)]">{{ r.severity }}</span></td>
                            <td class="px-4 py-2 text-xs text-slate-600 max-w-md truncate">{{ r.description }}</td>
                            <td class="px-4 py-2">
                                <div class="flex gap-1">
                                    <button @click="openRuleDetail(r.rule_id)"
                                            class="inline-flex items-center gap-1 rounded-lg border border-indigo-200 bg-indigo-50 px-2 py-1 text-xs text-indigo-700 hover:bg-indigo-100">
                                        <EyeIcon class="h-3 w-3" />
                                        Detay
                                    </button>
                                    <button @click="exclusionForm.rule_id = r.rule_id; activeTab = 'exclusions'"
                                            class="inline-flex items-center gap-1 rounded-lg border border-red-200 bg-red-50 px-2 py-1 text-xs text-red-700 hover:bg-red-100">
                                        <NoSymbolIcon class="h-3 w-3" />
                                        İstisna
                                    </button>
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 4 — İstisnalar
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'exclusions'" class="space-y-6">
            <div class="rounded-xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900 flex gap-3">
                <ExclamationTriangleIcon class="h-5 w-5 flex-shrink-0 text-amber-600" />
                <div>
                    <strong>Kural İstisnaları (False Positive):</strong> CRS kuralı yanlış tetikleniyorsa Rule ID'yi buraya ekleyerek devre dışı bırakabilirsiniz. Global (tüm site) veya per-domain.
                </div>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">Yeni İstisna Ekle</h3></div>
                <form @submit.prevent="addExclusion" class="grid grid-cols-1 md:grid-cols-4 gap-3 p-5">
                    <input v-model="exclusionForm.rule_id" placeholder="942100 (6 haneli)" maxlength="6"
                           class="rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                    <input v-model="exclusionForm.domain_name" placeholder="example.com (boş = global)"
                           class="rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                    <input v-model="exclusionForm.reason" placeholder="Sebep..." maxlength="500"
                           class="rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                    <button type="submit" :disabled="exclusionForm.processing || !exclusionForm.rule_id"
                            class="rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-700 disabled:opacity-50">
                        <PlusIcon class="h-4 w-4 inline" /> Ekle
                    </button>
                </form>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                <div class="border-b border-slate-200 px-5 py-3">
                    <h3 class="text-base font-semibold">Mevcut İstisnalar ({{ exclusions?.length || 0 }})</h3>
                </div>
                <div v-if="!exclusions || exclusions.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">Henüz istisna yok.</div>
                <table v-else class="min-w-full text-sm">
                    <thead class="bg-slate-50 text-xs uppercase text-slate-500">
                        <tr><th class="px-4 py-2 text-left">Rule ID</th><th class="px-4 py-2 text-left">Domain</th><th class="px-4 py-2 text-left">Sebep</th><th class="px-4 py-2 text-left">Ekleyen</th><th class="px-4 py-2 text-left">Eklenme</th><th class="px-4 py-2"></th></tr>
                    </thead>
                    <tbody class="divide-y divide-slate-100">
                        <tr v-for="ex in exclusions" :key="ex.id" class="hover:bg-slate-50">
                            <td class="px-4 py-2 font-mono font-bold text-amber-700">{{ ex.rule_id }}</td>
                            <td class="px-4 py-2 font-mono text-xs">{{ ex.domain_name || '— (global)' }}</td>
                            <td class="px-4 py-2 text-xs text-slate-600 max-w-xs truncate">{{ ex.reason || '—' }}</td>
                            <td class="px-4 py-2 text-xs">{{ ex.created_by_name || '—' }}</td>
                            <td class="px-4 py-2 text-xs text-slate-500">{{ formatTime(ex.created_at) }}</td>
                            <td class="px-4 py-2 text-right">
                                <button @click="removeExclusion(ex.id)" class="rounded p-1.5 text-red-500 hover:bg-red-50"><TrashIcon class="h-4 w-4" /></button>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 5 — Audit Log
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'audit'" class="space-y-6">
            <div class="flex items-center justify-between">
                <div class="text-sm text-slate-600">{{ auditResults.total || 0 }} olay · sayfa {{ auditResults.page }}</div>
                <button @click="refreshAudit" :disabled="auditRefreshing"
                        class="inline-flex items-center gap-2 rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white hover:bg-indigo-700 disabled:opacity-50">
                    <ArrowPathIcon class="h-4 w-4" :class="{ 'animate-spin': auditRefreshing }" />
                    {{ auditRefreshing ? 'Senkronize ediliyor…' : 'modsec_audit.log Yenile' }}
                </button>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm p-5">
                <div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-6 gap-3">
                    <input v-model="auditFilter.q" placeholder="URI/Sebep ara..." class="rounded-lg border border-slate-300 px-3 py-2 text-xs" />
                    <input v-model="auditFilter.rule_id" placeholder="Rule ID" class="rounded-lg border border-slate-300 px-3 py-2 font-mono text-xs" />
                    <input v-model="auditFilter.source_ip" placeholder="IP" class="rounded-lg border border-slate-300 px-3 py-2 font-mono text-xs" />
                    <input v-model="auditFilter.domain" placeholder="Domain" class="rounded-lg border border-slate-300 px-3 py-2 text-xs" />
                    <select v-model="auditFilter.severity" class="rounded-lg border border-slate-300 px-3 py-2 text-xs">
                        <option value="">Tüm seviyeler</option>
                        <option v-for="s in severities" :key="s" :value="s">{{ s }}</option>
                    </select>
                    <button @click="searchAudit" :disabled="auditSearching"
                            class="rounded-lg bg-indigo-600 px-3 py-2 text-xs font-semibold text-white hover:bg-indigo-700 disabled:opacity-50">
                        <MagnifyingGlassIcon class="h-3.5 w-3.5 inline" /> Ara
                    </button>
                </div>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                <div v-if="!auditResults.results || auditResults.results.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">
                    Eşleşen kayıt yok. "Yenile" tıklayarak modsec_audit.log'tan çek.
                </div>
                <div v-else class="overflow-x-auto">
                    <table class="min-w-full text-sm">
                        <thead class="bg-slate-50 text-xs uppercase text-slate-500">
                            <tr><th class="px-4 py-2 text-left">Zaman</th><th class="px-4 py-2 text-left">IP</th><th class="px-4 py-2 text-left">Ülke</th><th class="px-4 py-2 text-left">Domain</th><th class="px-4 py-2 text-left">URI</th><th class="px-4 py-2 text-left">Rule</th><th class="px-4 py-2 text-left">Severity</th><th class="px-4 py-2 text-left">Aksiyon</th><th class="px-4 py-2"></th></tr>
                        </thead>
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="ev in auditResults.results" :key="ev.id" class="hover:bg-slate-50 cursor-pointer" @click="openEventDetail(ev.id)">
                                <td class="px-4 py-2 text-xs text-slate-500">{{ formatTime(ev.event_at) }}</td>
                                <td class="px-4 py-2 font-mono text-xs">{{ ev.source_ip }}</td>
                                <td class="px-4 py-2">
                                    <img v-if="ev.country_code" :src="flagUrl(ev.country_code)" :alt="ev.country_code" class="w-5 h-3.5 rounded-sm" loading="lazy" />
                                </td>
                                <td class="px-4 py-2 text-xs">{{ ev.domain_name || '—' }}</td>
                                <td class="px-4 py-2 font-mono text-xs max-w-xs truncate" :title="ev.uri">{{ ev.method }} {{ ev.uri }}</td>
                                <td class="px-4 py-2">
                                    <button @click.stop="openRuleDetail(ev.rule_id)"
                                            class="font-mono font-bold text-amber-700 hover:underline">
                                        {{ ev.rule_id }}
                                    </button>
                                </td>
                                <td class="px-4 py-2"><span :class="['inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium ring-1', severityBadge(ev.severity)]">{{ ev.severity }}</span></td>
                                <td class="px-4 py-2">
                                    <span :class="['inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium', ev.action_taken === 'blocked' ? 'bg-red-100 text-red-700' : 'bg-emerald-100 text-emerald-700']">
                                        {{ ev.action_taken }}
                                    </span>
                                </td>
                                <td class="px-4 py-2" @click.stop>
                                    <div class="flex gap-1">
                                        <button @click="openEventDetail(ev.id)" title="Detay"
                                                class="rounded border border-indigo-200 bg-indigo-50 px-2 py-1 text-[10px] text-indigo-700 hover:bg-indigo-100">
                                            <EyeIcon class="h-3 w-3 inline" />
                                        </button>
                                        <button @click="quickExcludeFromAudit(ev.id)" title="Bu kuralı istisna yap"
                                                class="rounded border border-slate-200 bg-slate-50 px-2 py-1 text-[10px] hover:bg-slate-100">
                                            İstisna
                                        </button>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 6 — IP Whitelist
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'whitelist'" class="space-y-6">
            <div class="rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-sm text-emerald-900 flex gap-3">
                <ShieldCheckIcon class="h-5 w-5 flex-shrink-0 text-emerald-600" />
                <div><strong>ModSecurity Bypass:</strong> Bu IP'ler ModSecurity kurallarından geçmez (ofis, monitoring, partner servisleri için).</div>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">Whitelist'e IP Ekle</h3></div>
                <form @submit.prevent="addWhitelist" class="grid grid-cols-1 md:grid-cols-5 gap-3 p-5">
                    <input v-model="whitelistForm.ip_or_cidr" placeholder="1.2.3.4 veya 10.0.0.0/24" class="rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                    <input v-model="whitelistForm.domain_name" placeholder="example.com (boş = global)" class="rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                    <input v-model="whitelistForm.label" placeholder="Etiket" class="rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                    <input v-model="whitelistForm.reason" placeholder="Sebep" class="rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                    <button type="submit" :disabled="whitelistForm.processing"
                            class="rounded-lg bg-emerald-600 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-700 disabled:opacity-50">
                        <PlusIcon class="h-4 w-4 inline" /> Ekle
                    </button>
                </form>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                <div v-if="!whitelist || whitelist.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">Henüz IP yok.</div>
                <table v-else class="min-w-full text-sm">
                    <thead class="bg-slate-50 text-xs uppercase text-slate-500">
                        <tr><th class="px-4 py-2 text-left">IP/CIDR</th><th class="px-4 py-2 text-left">Domain</th><th class="px-4 py-2 text-left">Etiket</th><th class="px-4 py-2 text-left">Sebep</th><th class="px-4 py-2"></th></tr>
                    </thead>
                    <tbody class="divide-y divide-slate-100">
                        <tr v-for="w in whitelist" :key="w.id" class="hover:bg-slate-50">
                            <td class="px-4 py-2 font-mono font-bold">{{ w.ip_or_cidr }}</td>
                            <td class="px-4 py-2 text-xs">{{ w.domain_name || '— (global)' }}</td>
                            <td class="px-4 py-2 text-xs">{{ w.label || '—' }}</td>
                            <td class="px-4 py-2 text-xs text-slate-500 max-w-xs truncate">{{ w.reason || '—' }}</td>
                            <td class="px-4 py-2 text-right">
                                <button @click="removeWhitelist(w.id, w.ip_or_cidr)" class="rounded p-1.5 text-red-500 hover:bg-red-50"><TrashIcon class="h-4 w-4" /></button>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 7 — Özel Kurallar
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'custom'" class="space-y-6">
            <div class="rounded-xl border border-purple-200 bg-purple-50 p-4 text-sm text-purple-900 flex gap-3">
                <CodeBracketIcon class="h-5 w-5 flex-shrink-0 text-purple-600" />
                <div><strong>Özel SecRule Editör:</strong> CRS'in dışında kendi ModSecurity kurallarınızı tanımlayabilirsiniz. Syntax: <code class="font-mono">SecRule REQUEST_URI "@rx pattern" "id:N,phase:2,deny"</code></div>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">Yeni Özel Kural</h3></div>
                <form @submit.prevent="addCustomRule" class="p-5 space-y-3">
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <input v-model="customRuleForm.name" placeholder="Kural adı" maxlength="100"
                               class="rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                        <input v-model="customRuleForm.domain_name" placeholder="example.com (boş = global)"
                               class="rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                    </div>
                    <input v-model="customRuleForm.description" placeholder="Açıklama" maxlength="500"
                           class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                    <textarea v-model="customRuleForm.rule_content" rows="6"
                              :placeholder="`SecRule REQUEST_URI &quot;@rx /wp-admin/.*\\.php&quot; \\\n    &quot;id:100001,phase:1,deny,status:403,msg:'Block direct PHP access'&quot;`"
                              class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-xs"></textarea>
                    <p v-if="customRuleForm.errors?.rule_content" class="text-xs text-red-600">{{ customRuleForm.errors.rule_content }}</p>
                    <button type="submit" :disabled="customRuleForm.processing"
                            class="inline-flex items-center gap-2 rounded-lg bg-purple-600 px-5 py-2 text-sm font-semibold text-white hover:bg-purple-700 disabled:opacity-50">
                        <PlusIcon class="h-4 w-4" /> Kural Ekle
                    </button>
                </form>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                <div v-if="!custom_rules || custom_rules.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">Henüz özel kural yok.</div>
                <div v-else class="divide-y divide-slate-100">
                    <div v-for="r in custom_rules" :key="r.id" class="p-5 hover:bg-slate-50">
                        <div class="flex items-start justify-between gap-4 mb-3">
                            <div class="flex-1 min-w-0">
                                <h4 class="font-semibold text-sm">{{ r.name }}</h4>
                                <p class="text-xs text-slate-500 mt-1">{{ r.description || 'Açıklama yok' }}</p>
                                <p class="text-[10px] text-slate-400 mt-1">{{ r.domain_name || 'Global' }} · {{ r.category }} · {{ r.created_by_name || '—' }}</p>
                            </div>
                            <div class="flex items-center gap-2 flex-shrink-0">
                                <button @click="toggleCustomRule(r.id)"
                                        :class="['relative inline-flex h-5 w-9 items-center rounded-full transition', r.is_enabled ? 'bg-emerald-600' : 'bg-slate-300']">
                                    <span :class="['inline-block h-3.5 w-3.5 transform rounded-full bg-white transition', r.is_enabled ? 'translate-x-5' : 'translate-x-1']"></span>
                                </button>
                                <button @click="removeCustomRule(r.id, r.name)" class="rounded p-1.5 text-red-500 hover:bg-red-50"><TrashIcon class="h-4 w-4" /></button>
                            </div>
                        </div>
                        <pre class="bg-slate-50 rounded-lg p-3 text-[10px] font-mono whitespace-pre-wrap max-h-32 overflow-y-auto">{{ r.rule_content }}</pre>
                    </div>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 8 — CRS Update
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'crs'" class="space-y-6">
            <div class="rounded-xl border border-sky-200 bg-sky-50 p-4 text-sm text-sky-900 flex gap-3">
                <SparklesIcon class="h-5 w-5 flex-shrink-0 text-sky-600" />
                <div><strong>OWASP CRS Güncellemesi:</strong> GitHub'dan yeni Core Rule Set sürümünü indirir, mevcut config'i yedekler ve kurar.</div>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm p-6">
                <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
                    <div>
                        <p class="text-xs uppercase font-medium text-slate-500 mb-1">Kurulu Sürüm</p>
                        <p class="text-3xl font-bold">{{ crs_info?.installed || '—' }}</p>
                    </div>
                    <div>
                        <p class="text-xs uppercase font-medium text-slate-500 mb-1">En Son Sürüm</p>
                        <p class="text-3xl font-bold text-emerald-600">{{ crs_info?.latest || '—' }}</p>
                    </div>
                    <div class="flex items-center">
                        <button v-if="crs_info?.update_available" @click="updateCrs" :disabled="crsUpdating"
                                class="w-full inline-flex items-center justify-center gap-2 rounded-lg bg-sky-600 px-5 py-3 text-sm font-semibold text-white hover:bg-sky-700 disabled:opacity-50">
                            <ArrowPathIcon class="h-4 w-4" :class="{ 'animate-spin': crsUpdating }" />
                            {{ crsUpdating ? 'Güncelleniyor…' : 'Şimdi Güncelle' }}
                        </button>
                        <span v-else class="text-sm text-emerald-600 font-medium flex items-center gap-1"><CheckCircleIcon class="h-5 w-5" /> Güncel</span>
                    </div>
                </div>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">Güncelleme Geçmişi</h3></div>
                <div v-if="!crs_history || crs_history.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">Henüz güncelleme yapılmamış.</div>
                <table v-else class="min-w-full text-sm">
                    <thead class="bg-slate-50 text-xs uppercase text-slate-500">
                        <tr><th class="px-4 py-2 text-left">Zaman</th><th class="px-4 py-2 text-left">Önceki</th><th class="px-4 py-2 text-left">Yeni</th><th class="px-4 py-2 text-left">Durum</th><th class="px-4 py-2 text-left">Tetikleyen</th></tr>
                    </thead>
                    <tbody class="divide-y divide-slate-100">
                        <tr v-for="h in crs_history" :key="h.id">
                            <td class="px-4 py-2 text-xs text-slate-500">{{ formatTime(h.created_at) }}</td>
                            <td class="px-4 py-2 font-mono">{{ h.from_version || '—' }}</td>
                            <td class="px-4 py-2 font-mono font-bold text-emerald-600">{{ h.to_version }}</td>
                            <td class="px-4 py-2">
                                <span :class="['inline-flex rounded-full px-2 py-0.5 text-[10px] font-medium', h.status === 'success' ? 'bg-emerald-100 text-emerald-700' : 'bg-red-100 text-red-700']">{{ h.status }}</span>
                            </td>
                            <td class="px-4 py-2 text-xs">{{ h.triggered_by || '—' }}</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 9 — Test Aracı
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'test'" class="space-y-6">
            <div class="rounded-xl border border-cyan-200 bg-cyan-50 p-4 text-sm text-cyan-900 flex gap-3">
                <BeakerIcon class="h-5 w-5 flex-shrink-0 text-cyan-600" />
                <div><strong>Saldırı Simülasyon:</strong> Bir HTTP isteğini ModSecurity kurallarına karşı simüle eder. "Bu istek gerçek olsaydı bloklanır mıydı?"</div>
            </div>

            <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-base font-semibold">İstek Detayı</h3></div>
                <form @submit.prevent="runTest" class="p-5 space-y-3">
                    <div class="grid grid-cols-1 md:grid-cols-4 gap-3">
                        <select v-model="testForm.method" class="rounded-lg border border-slate-300 px-3 py-2 text-sm font-mono">
                            <option>GET</option><option>POST</option><option>PUT</option><option>PATCH</option><option>DELETE</option>
                        </select>
                        <input v-model="testForm.uri" placeholder="/admin?id=1' OR 1=1--" class="md:col-span-3 rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                    </div>
                    <textarea v-model="testForm.headers" rows="2" placeholder="Headers (her satıra bir tane)" class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-xs"></textarea>
                    <textarea v-model="testForm.body" rows="3" placeholder="POST body (opsiyonel)" class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-xs"></textarea>
                    <button type="submit" :disabled="testRunning"
                            class="inline-flex items-center gap-2 rounded-lg bg-cyan-600 px-5 py-2 text-sm font-semibold text-white hover:bg-cyan-700 disabled:opacity-50">
                        <BeakerIcon class="h-4 w-4" />
                        {{ testRunning ? 'Test ediliyor…' : 'Test Et' }}
                    </button>
                </form>
            </div>

            <div v-if="testResult" class="rounded-xl border bg-white shadow-sm overflow-hidden"
                 :class="testResult.would_block ? 'border-red-300' : 'border-emerald-300'">
                <div :class="['px-5 py-3 flex items-center justify-between', testResult.would_block ? 'bg-red-50' : 'bg-emerald-50']">
                    <h3 class="text-base font-semibold flex items-center gap-2">
                        <XCircleIcon v-if="testResult.would_block" class="h-5 w-5 text-red-600" />
                        <CheckCircleIcon v-else class="h-5 w-5 text-emerald-600" />
                        {{ testResult.would_block ? `BLOKLU (action: ${testResult.action})` : 'GEÇERLİ — Bloklanmaz' }}
                    </h3>
                    <span class="text-sm font-mono">Anomaly score: <strong>{{ testResult.anomaly_score }}</strong></span>
                </div>
                <div class="p-5">
                    <p class="text-sm font-medium mb-3">Tetiklenen Kurallar ({{ testResult.matched_rules?.length || 0 }})</p>
                    <div v-if="!testResult.matched_rules || testResult.matched_rules.length === 0" class="text-sm text-slate-500">Hiçbir kural tetiklenmedi.</div>
                    <div v-else class="space-y-2">
                        <div v-for="(rule, i) in testResult.matched_rules" :key="i" class="rounded-lg ring-1 ring-slate-200 px-3 py-2 flex items-center gap-3">
                            <span class="font-mono font-bold text-amber-700">{{ rule.rule_id }}</span>
                            <span :class="['inline-flex rounded-full px-2 py-0.5 text-[10px] font-medium ring-1', severityBadge(rule.severity)]">{{ rule.severity }}</span>
                            <span class="text-sm flex-1">{{ rule.category }}</span>
                            <span class="text-xs font-mono text-red-600">+{{ rule.score }}</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 10 — Raporlar
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'reports'" class="space-y-6">
            <div v-if="reportsLoading" class="rounded-xl border border-slate-200 bg-white p-12 text-center text-sm text-slate-500">
                <ArrowPathIcon class="h-8 w-8 mx-auto mb-2 animate-spin text-indigo-500" />
                Raporlar yükleniyor…
            </div>
            <div v-else-if="!reports" class="rounded-xl border border-amber-200 bg-amber-50 p-6 text-sm text-amber-800">
                Henüz veri yok. Audit log'tan senkronize ettikten sonra rapor üretilir.
            </div>
            <template v-else>
                <!-- 30 günlük trend -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm p-5">
                    <div class="flex items-center gap-2 mb-4">
                        <PresentationChartLineIcon class="h-5 w-5 text-indigo-500" />
                        <h3 class="text-base font-semibold">30 Günlük Saldırı Trendi</h3>
                    </div>
                    <div v-if="!reports.daily_trend_30d?.length" class="py-8 text-center text-sm text-slate-500">Veri yok.</div>
                    <div v-else class="flex items-end gap-1 h-32">
                        <div v-for="d in reports.daily_trend_30d" :key="d.day" class="flex-1 flex flex-col items-center group">
                            <div :style="{ height: `${(d.blocked / Math.max(1, ...reports.daily_trend_30d.map(x => x.blocked))) * 100}%`, minHeight: '2px' }"
                                 class="w-full bg-gradient-to-t from-rose-600/70 to-pink-500 rounded-t"
                                 :title="`${d.day}: ${d.blocked} blok, ${d.unique_ips} IP`"></div>
                            <span class="text-[8px] text-slate-400 mt-1 opacity-0 group-hover:opacity-100 transition">{{ d.day?.slice(5) }}</span>
                        </div>
                    </div>
                </div>

                <!-- Category breakdown + Response codes -->
                <div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
                    <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                        <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-sm font-semibold">Kategori Kırılımı (7g)</h3></div>
                        <div v-if="!reports.category_breakdown?.length" class="px-5 py-12 text-center text-sm text-slate-500">Veri yok.</div>
                        <div v-else class="p-5 space-y-2">
                            <div v-for="(cat, i) in reports.category_breakdown" :key="i" class="flex items-center gap-3">
                                <span class="text-[10px] text-slate-400 w-5">{{ i + 1 }}</span>
                                <span class="text-xs font-mono w-32 truncate">{{ cat.category }}</span>
                                <div class="flex-1 h-3 bg-slate-100 rounded-full overflow-hidden">
                                    <div :style="{ width: `${(cat.count / reports.category_breakdown[0].count) * 100}%` }"
                                         class="h-full bg-gradient-to-r from-purple-500 to-fuchsia-600"></div>
                                </div>
                                <span class="text-xs font-mono font-bold text-slate-700 w-12 text-right">{{ formatNumber(cat.count) }}</span>
                            </div>
                        </div>
                    </div>

                    <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                        <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-sm font-semibold">Action Dağılımı (7g)</h3></div>
                        <div v-if="!reports.response_code_dist?.length" class="px-5 py-12 text-center text-sm text-slate-500">Veri yok.</div>
                        <div v-else class="p-5 space-y-3">
                            <div v-for="rc in reports.response_code_dist" :key="rc.action_taken" class="flex items-center justify-between">
                                <span :class="['inline-flex items-center rounded-full px-3 py-1 text-xs font-medium',
                                    rc.action_taken === 'blocked' ? 'bg-red-100 text-red-700' :
                                    rc.action_taken === 'passed' ? 'bg-emerald-100 text-emerald-700' : 'bg-amber-100 text-amber-700']">
                                    {{ rc.action_taken }}
                                </span>
                                <span class="font-mono font-bold text-lg">{{ formatNumber(rc.count) }}</span>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Top attacked domains -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                    <div class="border-b border-slate-200 px-5 py-3"><h3 class="text-sm font-semibold">En Çok Saldırı Alan Domain'ler (7g)</h3></div>
                    <div v-if="!reports.top_attacked_domains?.length" class="px-5 py-12 text-center text-sm text-slate-500">Veri yok.</div>
                    <table v-else class="min-w-full text-sm">
                        <thead class="bg-slate-50 text-xs uppercase text-slate-500">
                            <tr><th class="px-4 py-2 text-left">#</th><th class="px-4 py-2 text-left">Domain</th><th class="px-4 py-2 text-right">Saldırı</th><th class="px-4 py-2 text-right">Benzersiz IP</th></tr>
                        </thead>
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="(d, i) in reports.top_attacked_domains" :key="d.domain_name">
                                <td class="px-4 py-2 text-slate-400">{{ i + 1 }}</td>
                                <td class="px-4 py-2 font-mono text-xs">{{ d.domain_name }}</td>
                                <td class="px-4 py-2 text-right font-bold text-red-600">{{ formatNumber(d.attacks) }}</td>
                                <td class="px-4 py-2 text-right text-slate-500">{{ formatNumber(d.unique_attackers) }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>

                <!-- Repeat offenders -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden">
                    <div class="border-b border-slate-200 px-5 py-3 flex items-center gap-2">
                        <ShieldExclamationIcon class="h-5 w-5 text-red-500" />
                        <h3 class="text-sm font-semibold">Tekrarcı Saldırganlar (7g, 10+ hit)</h3>
                    </div>
                    <div v-if="!reports.repeat_offenders?.length" class="px-5 py-12 text-center text-sm text-slate-500">Henüz tekrarcı yok.</div>
                    <table v-else class="min-w-full text-sm">
                        <thead class="bg-slate-50 text-xs uppercase text-slate-500">
                            <tr><th class="px-4 py-2 text-left">IP</th><th class="px-4 py-2 text-left">Ülke</th><th class="px-4 py-2 text-right">Hit</th><th class="px-4 py-2 text-right">Farklı Kural</th><th class="px-4 py-2 text-left">Son Görülme</th></tr>
                        </thead>
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="r in reports.repeat_offenders" :key="r.source_ip" class="hover:bg-slate-50">
                                <td class="px-4 py-2 font-mono text-xs">{{ r.source_ip }}</td>
                                <td class="px-4 py-2">
                                    <img v-if="r.country_code" :src="flagUrl(r.country_code)" :alt="r.country_code" class="w-5 h-3.5 rounded-sm" loading="lazy" />
                                </td>
                                <td class="px-4 py-2 text-right font-bold text-red-600">{{ formatNumber(r.hits) }}</td>
                                <td class="px-4 py-2 text-right">{{ r.distinct_rules }}</td>
                                <td class="px-4 py-2 text-xs text-slate-500">{{ formatTime(r.last_seen) }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </template>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 11 — Vendor'lar
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'vendors'" class="space-y-6">
            <div class="rounded-xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900 flex gap-3">
                <PuzzlePieceIcon class="h-5 w-5 flex-shrink-0 text-amber-600" />
                <div>
                    <strong>Vendor RuleSet Yöneticisi:</strong> Birden fazla WAF rule vendor'ını paralel çalıştırın.
                    OWASP CRS (ücretsiz), Comodo (kayıt gerekir), Atomicorp (community + commercial) vb. Her vendor kendi
                    rule ID aralığında çalışır, çakışmaz.
                </div>
            </div>

            <div v-if="vendorsLoading" class="rounded-xl border border-slate-200 bg-white p-12 text-center">
                <ArrowPathIcon class="h-8 w-8 mx-auto mb-2 animate-spin text-amber-500" />
                <p class="text-sm text-slate-500">Vendor listesi yükleniyor…</p>
            </div>
            <div v-else-if="vendors?.length" class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div v-for="v in vendors" :key="v.slug"
                     :class="['rounded-xl border bg-white shadow-sm overflow-hidden',
                         v.is_installed || v.installed_version ? 'border-emerald-300 ring-1 ring-emerald-200' : 'border-slate-200']">
                    <div class="border-b border-slate-100 px-5 py-3 flex items-center justify-between gap-3">
                        <div class="flex items-center gap-2 min-w-0">
                            <PuzzlePieceIcon class="h-5 w-5 flex-shrink-0"
                                             :class="v.is_installed || v.installed_version ? 'text-emerald-600' : 'text-slate-400'" />
                            <h3 class="text-sm font-semibold truncate">{{ v.name }}</h3>
                            <span v-if="v.is_official" class="inline-flex items-center rounded-full bg-emerald-100 px-1.5 py-0.5 text-[9px] font-bold text-emerald-700">RESMİ</span>
                        </div>
                        <a v-if="v.source_url" :href="v.source_url" target="_blank" class="text-slate-400 hover:text-indigo-600">
                            <ArrowTopRightOnSquareIcon class="h-4 w-4" />
                        </a>
                    </div>

                    <div class="p-5 space-y-3 text-xs">
                        <p class="text-slate-600 line-clamp-2 min-h-[2rem]">{{ v.description }}</p>

                        <div class="grid grid-cols-2 gap-2 pt-2 border-t border-slate-100">
                            <div>
                                <span class="text-[10px] uppercase text-slate-500 font-medium">Versiyon</span>
                                <p class="font-mono text-sm">{{ v.installed_version || '—' }}</p>
                            </div>
                            <div>
                                <span class="text-[10px] uppercase text-slate-500 font-medium">Kural Sayısı</span>
                                <p class="font-mono text-sm">{{ formatNumber(v.rules_count) }}</p>
                            </div>
                        </div>

                        <div class="flex gap-2 pt-2 border-t border-slate-100">
                            <button v-if="!v.installed_version && !v.is_installed"
                                    @click="installVendor(v)"
                                    class="flex-1 inline-flex items-center justify-center gap-1.5 rounded-lg bg-amber-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-amber-700">
                                <PlusIcon class="h-3.5 w-3.5" />
                                Kur
                            </button>
                            <template v-else>
                                <button v-if="!v.is_official" @click="removeVendor(v.slug, v.name)"
                                        class="flex-1 inline-flex items-center justify-center gap-1 rounded-lg border border-red-200 bg-red-50 px-3 py-1.5 text-xs text-red-700 hover:bg-red-100">
                                    <TrashIcon class="h-3.5 w-3.5" />
                                    Kaldır
                                </button>
                                <span v-else class="flex-1 inline-flex items-center justify-center gap-1 rounded-lg bg-emerald-100 px-3 py-1.5 text-xs font-medium text-emerald-700">
                                    <CheckCircleIcon class="h-3.5 w-3.5" />
                                    Aktif
                                </span>
                            </template>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             MODAL — Rule Detail
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="ruleDetailOpen" @click.self="ruleDetailOpen = false"
             class="fixed inset-0 z-50 bg-black/60 backdrop-blur-sm flex items-center justify-center p-4 overflow-y-auto">
            <div class="bg-white rounded-2xl shadow-2xl max-w-3xl w-full max-h-[90vh] overflow-y-auto">
                <div class="sticky top-0 bg-white border-b border-slate-200 px-6 py-4 flex items-center justify-between z-10">
                    <h2 class="text-lg font-bold flex items-center gap-2">
                        <DocumentTextIcon class="h-5 w-5 text-indigo-600" />
                        Rule <span class="font-mono text-indigo-600">{{ ruleDetail?.rule_id }}</span>
                    </h2>
                    <button @click="ruleDetailOpen = false" class="text-slate-400 hover:text-slate-900"><XCircleIcon class="h-6 w-6" /></button>
                </div>

                <div v-if="ruleDetailLoading" class="py-16 text-center">
                    <ArrowPathIcon class="h-8 w-8 mx-auto animate-spin text-indigo-500" />
                </div>
                <div v-else-if="ruleDetail" class="p-6 space-y-5">
                    <!-- Meta info -->
                    <div class="grid grid-cols-2 md:grid-cols-4 gap-3">
                        <div><p class="text-[10px] uppercase text-slate-500 font-medium">Kategori</p><p class="text-sm font-semibold">{{ ruleDetail.category || '—' }}</p></div>
                        <div><p class="text-[10px] uppercase text-slate-500 font-medium">Severity</p><p><span :class="['inline-flex rounded-full px-2 py-0.5 text-[10px] font-medium ring-1', severityBadge(ruleDetail.severity)]">{{ ruleDetail.severity || '—' }}</span></p></div>
                        <div><p class="text-[10px] uppercase text-slate-500 font-medium">Tag</p><p class="font-mono text-xs">{{ ruleDetail.tag || '—' }}</p></div>
                        <div><p class="text-[10px] uppercase text-slate-500 font-medium">Phase</p><p class="font-mono text-xs">{{ ruleDetail.phase || '—' }}</p></div>
                    </div>

                    <div v-if="ruleDetail.description">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-1">Açıklama</p>
                        <p class="text-sm">{{ ruleDetail.description }}</p>
                    </div>

                    <!-- Status -->
                    <div class="grid grid-cols-3 gap-3">
                        <div :class="['rounded-lg p-3 text-center', ruleDetail.is_disabled ? 'bg-red-50 ring-1 ring-red-200' : 'bg-emerald-50 ring-1 ring-emerald-200']">
                            <p class="text-[10px] uppercase font-medium" :class="ruleDetail.is_disabled ? 'text-red-600' : 'text-emerald-600'">Durum</p>
                            <p class="text-sm font-bold" :class="ruleDetail.is_disabled ? 'text-red-800' : 'text-emerald-800'">
                                {{ ruleDetail.is_disabled ? 'Devre Dışı' : 'Aktif' }}
                            </p>
                        </div>
                        <div class="rounded-lg p-3 text-center bg-amber-50 ring-1 ring-amber-200">
                            <p class="text-[10px] uppercase font-medium text-amber-600">30 Gün Hit</p>
                            <p class="text-sm font-bold text-amber-800">{{ formatNumber(ruleDetail.total_hits_30d) }}</p>
                        </div>
                        <div class="rounded-lg p-3 text-center bg-indigo-50 ring-1 ring-indigo-200">
                            <p class="text-[10px] uppercase font-medium text-indigo-600">İstisna</p>
                            <p class="text-sm font-bold text-indigo-800">
                                {{ ruleDetail.is_excluded_globally ? 'Global' : (ruleDetail.domain_exclusions?.length ? `${ruleDetail.domain_exclusions.length} domain` : '—') }}
                            </p>
                        </div>
                    </div>

                    <!-- File path -->
                    <div v-if="ruleDetail.file_path">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-1">Konum</p>
                        <code class="text-xs font-mono bg-slate-50 rounded px-2 py-1">{{ ruleDetail.file_path }}</code>
                    </div>

                    <!-- Source code -->
                    <div v-if="ruleDetail.source">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-2">SecRule Source</p>
                        <pre class="bg-slate-950 text-slate-100 rounded-lg p-4 text-[11px] font-mono overflow-x-auto leading-relaxed max-h-72 overflow-y-auto">{{ ruleDetail.source }}</pre>
                    </div>

                    <!-- Hit history chart -->
                    <div v-if="ruleDetail.hit_history_30d?.length">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-2">30 Gün Hit Trendi</p>
                        <div class="flex items-end gap-0.5 h-20">
                            <div v-for="d in ruleDetail.hit_history_30d" :key="d.day"
                                 :style="{ height: `${(d.count / Math.max(1, ...ruleDetail.hit_history_30d.map(x => x.count))) * 100}%`, minHeight: '2px' }"
                                 class="flex-1 bg-gradient-to-t from-amber-600/70 to-yellow-500 rounded-t"
                                 :title="`${d.day}: ${d.count}`"></div>
                        </div>
                    </div>

                    <!-- Actions -->
                    <div class="flex gap-2 pt-4 border-t border-slate-200">
                        <button @click="toggleRuleFromDetail(ruleDetail.rule_id)"
                                :class="['flex-1 inline-flex items-center justify-center gap-2 rounded-lg px-4 py-2 text-sm font-medium',
                                    ruleDetail.is_disabled ? 'bg-emerald-600 text-white hover:bg-emerald-700' : 'bg-red-600 text-white hover:bg-red-700']">
                            {{ ruleDetail.is_disabled ? 'Tekrar Etkinleştir' : 'Devre Dışı Bırak' }}
                        </button>
                        <button @click="exclusionForm.rule_id = ruleDetail.rule_id; ruleDetailOpen = false; activeTab = 'exclusions'"
                                class="flex-1 inline-flex items-center justify-center gap-2 rounded-lg border border-amber-200 bg-amber-50 px-4 py-2 text-sm font-medium text-amber-700 hover:bg-amber-100">
                            İstisna Olarak Ekle
                        </button>
                    </div>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             MODAL — Audit Event Detail
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="eventDetailOpen" @click.self="eventDetailOpen = false"
             class="fixed inset-0 z-50 bg-black/60 backdrop-blur-sm flex items-center justify-center p-4 overflow-y-auto">
            <div class="bg-white rounded-2xl shadow-2xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
                <div class="sticky top-0 bg-white border-b border-slate-200 px-6 py-4 flex items-center justify-between z-10">
                    <h2 class="text-lg font-bold flex items-center gap-2">
                        <ShieldExclamationIcon class="h-5 w-5 text-red-600" />
                        Saldırı Detayı
                    </h2>
                    <button @click="eventDetailOpen = false" class="text-slate-400 hover:text-slate-900"><XCircleIcon class="h-6 w-6" /></button>
                </div>

                <div v-if="eventDetailLoading" class="py-16 text-center">
                    <ArrowPathIcon class="h-8 w-8 mx-auto animate-spin text-red-500" />
                </div>
                <div v-else-if="eventDetail" class="p-6 space-y-5">
                    <!-- Header -->
                    <div class="grid grid-cols-2 md:grid-cols-4 gap-3">
                        <div><p class="text-[10px] uppercase text-slate-500 font-medium">Zaman</p><p class="text-xs">{{ formatTime(eventDetail.event.event_at) }}</p></div>
                        <div>
                            <p class="text-[10px] uppercase text-slate-500 font-medium">Kaynak IP</p>
                            <p class="font-mono text-xs flex items-center gap-1.5">
                                <img v-if="eventDetail.event.country_code" :src="flagUrl(eventDetail.event.country_code)" class="w-4 h-3 rounded-sm" />
                                {{ eventDetail.event.source_ip }}
                            </p>
                        </div>
                        <div><p class="text-[10px] uppercase text-slate-500 font-medium">Aksiyon</p>
                            <span :class="['inline-flex rounded-full px-2 py-0.5 text-[10px] font-medium', eventDetail.event.action_taken === 'blocked' ? 'bg-red-100 text-red-700' : 'bg-emerald-100 text-emerald-700']">
                                {{ eventDetail.event.action_taken }}
                            </span>
                        </div>
                        <div><p class="text-[10px] uppercase text-slate-500 font-medium">Response</p>
                            <p class="font-mono text-xs font-bold" :class="eventDetail.event.response_code >= 400 ? 'text-red-600' : 'text-emerald-600'">{{ eventDetail.event.response_code || '—' }}</p>
                        </div>
                    </div>

                    <!-- Request line -->
                    <div class="rounded-lg bg-slate-50 ring-1 ring-slate-200 p-3">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-1">İstek</p>
                        <p class="font-mono text-sm">
                            <span class="font-bold text-indigo-600">{{ eventDetail.event.method }}</span>
                            <span class="ml-2">{{ eventDetail.event.uri }}</span>
                        </p>
                        <p class="text-[10px] text-slate-500 mt-1">Domain: <span class="font-mono">{{ eventDetail.event.domain_name || '—' }}</span></p>
                    </div>

                    <!-- Matched rules -->
                    <div v-if="eventDetail.all_matched_rules?.length">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-2">Eşleşen Kurallar ({{ eventDetail.all_matched_rules.length }})</p>
                        <div class="space-y-2">
                            <div v-for="(r, i) in eventDetail.all_matched_rules" :key="i" class="rounded-lg ring-1 ring-slate-200 px-3 py-2 flex items-center gap-3">
                                <button @click="openRuleDetail(r.rule_id)" class="font-mono font-bold text-amber-700 hover:underline">{{ r.rule_id }}</button>
                                <span :class="['inline-flex rounded-full px-2 py-0.5 text-[10px] font-medium ring-1', severityBadge(r.severity)]">{{ r.severity }}</span>
                                <span class="text-sm flex-1 truncate">{{ r.msg }}</span>
                            </div>
                        </div>
                    </div>

                    <!-- Matched data -->
                    <div v-if="eventDetail.matched_data">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-2">Eşleşen Veri</p>
                        <pre class="bg-amber-50 ring-1 ring-amber-200 rounded-lg p-3 text-[11px] font-mono overflow-x-auto">{{ JSON.stringify(eventDetail.matched_data, null, 2) }}</pre>
                    </div>

                    <!-- Request headers -->
                    <div v-if="eventDetail.request_headers">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-2">Request Headers</p>
                        <pre class="bg-slate-950 text-slate-100 rounded-lg p-3 text-[11px] font-mono overflow-x-auto leading-relaxed max-h-40 overflow-y-auto">{{ eventDetail.request_headers }}</pre>
                    </div>

                    <!-- Request body -->
                    <div v-if="eventDetail.request_body">
                        <p class="text-[10px] uppercase text-slate-500 font-medium mb-2">Request Body</p>
                        <pre class="bg-red-50 ring-1 ring-red-200 rounded-lg p-3 text-[11px] font-mono overflow-x-auto max-h-40 overflow-y-auto">{{ eventDetail.request_body }}</pre>
                    </div>

                    <!-- Actions -->
                    <div class="flex gap-2 pt-4 border-t border-slate-200">
                        <button @click="quickExcludeFromAudit(eventDetail.event.id); eventDetailOpen = false"
                                class="flex-1 rounded-lg bg-amber-600 px-4 py-2 text-sm font-medium text-white hover:bg-amber-700">
                            Bu Kuralı İstisna Yap
                        </button>
                        <button @click="whitelistForm.ip_or_cidr = eventDetail.event.source_ip; whitelistForm.reason = `Audit #${eventDetail.event.id}`; eventDetailOpen = false; activeTab = 'whitelist'"
                                class="flex-1 rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-2 text-sm font-medium text-emerald-700 hover:bg-emerald-100">
                            IP'yi Whitelist'e Ekle
                        </button>
                    </div>
                </div>
            </div>
        </div>

    </AdminLayout>
</template>
