<script setup>
import { ref, computed } from 'vue'
import { Head, useForm, router } from '@inertiajs/vue3'
import AdminLayout from '@/Layouts/AdminLayout.vue'
import {
    ShieldCheckIcon,
    PlusIcon,
    NoSymbolIcon,
    CheckCircleIcon,
    XCircleIcon,
    ChartBarIcon,
    LockClosedIcon,
    BeakerIcon,
    Cog6ToothIcon,
    ClockIcon,
    BoltIcon,
    SparklesIcon,
    StarIcon,
    TrashIcon,
    MagnifyingGlassIcon,
    ArrowPathIcon,
    PowerIcon,
    PencilIcon,
    DocumentTextIcon,
    UserGroupIcon,
} from '@heroicons/vue/24/outline'
import axios from 'axios'
import { useConfirm } from '@/composables/useConfirm'
import { useCountryFlag } from '@/composables/useCountryFlag'
import {
    FAIL2BAN_TEMPLATES,
    TEMPLATE_CATEGORIES,
    PRESETS,
    findTemplate,
} from '@/data/fail2banTemplates'

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

const props = defineProps({
    status:            Object,
    jails:             Array,
    jails_meta:        Array,
    whitelist:         Array,
    settings:          Object,
    stats:             Object,
    top_attackers:     Array,
    bans_by_jail:      Array,
    hourly_chart:      Array,
    banned_ips:        Array,
    history:           Array,
    available_filters: Array,
})

// ── Tabs ──────────────────────────────────────────────────────────────────
const activeTab = ref('dashboard')
const tabs = [
    { key: 'dashboard',  label: 'Genel Bakış',    icon: ChartBarIcon },
    { key: 'jails',      label: 'Jails',          icon: LockClosedIcon },
    { key: 'templates',  label: 'Şablonlar',      icon: SparklesIcon, badge: 'YENİ' },
    { key: 'banned',     label: 'Banlı IP',       icon: NoSymbolIcon, badge: 'YENİ' },
    { key: 'whitelist',  label: 'İzin Listesi',   icon: ShieldCheckIcon, badge: 'YENİ' },
    { key: 'settings',   label: 'Ayarlar',        icon: Cog6ToothIcon, badge: 'YENİ' },
    { key: 'filters',    label: 'Filtre Test',    icon: BeakerIcon, badge: 'YENİ' },
    { key: 'history',    label: 'Geçmiş',         icon: ClockIcon, badge: 'YENİ' },
]

// ── Jail form ─────────────────────────────────────────────────────────────
const jailForm = useForm({
    jail_name:    '',
    display_name: '',
    description:  '',
    template_slug: null,
    enabled:      true,
    port:         'ssh,22',
    filter:       '',
    logpath:      '/var/log/secure',
    maxretry:     5,
    findtime:     600,
    bantime:      3600,
    action:       '%(action_)s',
    ignoreip:     '',
    comment:      '',
})

const showJailForm = ref(false)

const submitJail = () => {
    jailForm.post(route('admin.fail2ban.jails.store'), {
        preserveScroll: true,
        onSuccess: () => {
            jailForm.reset()
            showJailForm.value = false
        },
    })
}

const editJail = (jail) => {
    jailForm.jail_name = jail.jail_name
    jailForm.display_name = jail.display_name || ''
    jailForm.description = jail.description || ''
    jailForm.template_slug = jail.template_slug
    jailForm.enabled = !! jail.is_enabled
    jailForm.port = jail.port
    jailForm.filter = jail.filter || ''
    jailForm.logpath = jail.logpath
    jailForm.maxretry = jail.maxretry
    jailForm.findtime = jail.findtime
    jailForm.bantime = jail.bantime
    jailForm.action = jail.action
    jailForm.ignoreip = jail.ignoreip || ''
    jailForm.comment = jail.comment || ''
    showJailForm.value = true
    activeTab.value = 'jails'
}

const applyTemplate = (template) => {
    jailForm.jail_name = template.slug
    jailForm.display_name = template.display_name
    jailForm.description = template.description
    jailForm.template_slug = template.slug
    jailForm.enabled = true
    jailForm.port = template.port
    jailForm.filter = template.filter
    jailForm.logpath = template.logpath
    jailForm.maxretry = template.maxretry
    jailForm.findtime = template.findtime
    jailForm.bantime = template.bantime
    jailForm.action = template.action
    showJailForm.value = true
    activeTab.value = 'jails'
}

const deleteJail = async (jail) => {
    const ok = await ask({
        title: 'Jail Sil',
        message: `'${jail}' jail'i tamamen silinecek. Bu jail'deki tüm banlı IP'ler de serbest bırakılacak. Devam?`,
        variant: 'danger',
        confirmText: 'Sil',
        cancelText: 'İptal',
    })
    if (! ok) return
    router.delete(route('admin.fail2ban.jails.delete', jail), { preserveScroll: true })
}

const toggleJail = (jail) => {
    router.post(route('admin.fail2ban.jails.toggle', jail), {}, { preserveScroll: true })
}

// ── Ban / Unban ───────────────────────────────────────────────────────────
const banForm   = useForm({ jail: 'sshd', ip: '', comment: '' })
const unbanForm = useForm({ jail: 'sshd', ip: '' })
const bulkBanText = ref('')
const bulkBanJail = ref('sshd')
const bulkBanRunning = ref(false)

const ban = () => banForm.post(route('admin.fail2ban.ban'), { preserveScroll: true })
const unban = () => unbanForm.post(route('admin.fail2ban.unban'), { preserveScroll: true })

const doBulkBan = async () => {
    const ips = bulkBanText.value
        .split('\n')
        .map(s => s.trim())
        .filter(s => s.length > 0)

    if (ips.length === 0) {
        window.$toast?.warning?.('IP listesi boş')
        return
    }

    const ok = await ask({
        title: 'Toplu Ban',
        message: `${ips.length} IP, '${bulkBanJail.value}' jail'inde banlanacak. Devam?`,
        variant: 'danger',
        confirmText: 'Toplu Banla',
        cancelText: 'İptal',
    })
    if (! ok) return

    bulkBanRunning.value = true
    try {
        const { data } = await axios.post(route('admin.fail2ban.bulk_ban'), {
            jail: bulkBanJail.value,
            ips,
            confirm: 'TOPLU BAN',
        })
        if (data.success) {
            window.$toast?.success?.(`${data.banned}/${data.requested} IP banlandı`)
            bulkBanText.value = ''
            router.reload({ only: ['banned_ips', 'stats'], preserveScroll: true })
        }
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        bulkBanRunning.value = false
    }
}

const unbanAll = async (jail) => {
    const ok = await ask({
        title: 'Tümünü Unban',
        message: `'${jail}' jail'indeki TÜM banlı IP'ler serbest bırakılacak. Devam?`,
        variant: 'danger',
        confirmText: 'Tümünü Unban',
        cancelText: 'İptal',
    })
    if (! ok) return
    router.post(route('admin.fail2ban.unban_all', jail), { confirm: 'TUMUNU BOSALT' }, { preserveScroll: true })
}

const quickUnban = (jail, ip) => {
    router.post(route('admin.fail2ban.unban'), { jail, ip }, { preserveScroll: true })
}

// ── Whitelist ─────────────────────────────────────────────────────────────
const whitelistForm = useForm({
    ip_or_cidr: '',
    label:      '',
    comment:    '',
})

const submitWhitelist = () => {
    whitelistForm.post(route('admin.fail2ban.whitelist.add'), {
        preserveScroll: true,
        onSuccess: () => whitelistForm.reset(),
    })
}

const removeWhitelist = async (id, ip) => {
    const ok = await ask({
        title: 'İzin Listesinden Sil',
        message: `${ip} izin listesinden silinecek. Artık banlanabilir hale gelecek.`,
        variant: 'danger',
        confirmText: 'Sil',
        cancelText: 'İptal',
    })
    if (! ok) return
    router.delete(route('admin.fail2ban.whitelist.remove', id), { preserveScroll: true })
}

// ── Settings ──────────────────────────────────────────────────────────────
const settingsForm = useForm({
    default_bantime:   parseInt(props.settings?.default_bantime ?? '3600'),
    default_findtime:  parseInt(props.settings?.default_findtime ?? '600'),
    default_maxretry:  parseInt(props.settings?.default_maxretry ?? '5'),
    default_action:    props.settings?.default_action ?? '%(action_mwl)s',
    destemail:         props.settings?.destemail ?? '',
    sender:            props.settings?.sender ?? 'fail2ban@localhost',
    dbpurgeage:        parseInt(props.settings?.dbpurgeage ?? '86400'),
    dbmaxmatches:      parseInt(props.settings?.dbmaxmatches ?? '10'),
    logtarget:         props.settings?.logtarget ?? '/var/log/fail2ban.log',
    loglevel:          props.settings?.loglevel ?? 'INFO',
    notify_on_ban:     props.settings?.notify_on_ban === '1',
    recidive_enabled:  props.settings?.recidive_enabled === '1',
    preset_mode:       props.settings?.preset_mode ?? 'balanced',
})

const submitSettings = () => {
    const payload = {
        ...settingsForm.data(),
        notify_on_ban:    settingsForm.notify_on_ban    ? '1' : '0',
        recidive_enabled: settingsForm.recidive_enabled ? '1' : '0',
    }
    router.patch(route('admin.fail2ban.settings.update'), payload, { preserveScroll: true })
}

const applyPreset = (presetKey) => {
    router.post(route('admin.fail2ban.preset.apply'), { preset: presetKey }, {
        preserveScroll: true,
        onSuccess: () => {
            // Update form to reflect new values
            const preset = PRESETS[presetKey]
            if (preset) {
                settingsForm.default_maxretry = preset.default_maxretry
                settingsForm.default_findtime = preset.default_findtime
                settingsForm.default_bantime = preset.default_bantime
                settingsForm.recidive_enabled = preset.recidive_enabled
                settingsForm.preset_mode = presetKey
            }
        },
    })
}

// ── Filter test ───────────────────────────────────────────────────────────
const filterTestForm = ref({
    filter: 'sshd',
    log_line: 'Failed password for root from 1.2.3.4 port 22 ssh2',
})
const filterTestResult = ref(null)
const filterTesting = ref(false)

const doFilterTest = async () => {
    filterTesting.value = true
    filterTestResult.value = null
    try {
        const { data } = await axios.post(route('admin.fail2ban.filter.test'), filterTestForm.value)
        if (data.success) {
            filterTestResult.value = data
        }
    } catch (e) {
        window.$toast?.error?.(e.response?.data?.error || e.message)
    } finally {
        filterTesting.value = false
    }
}

// ── Service control ───────────────────────────────────────────────────────
const restartFail2ban = async () => {
    const ok = await ask({
        title: 'fail2ban Restart',
        message: 'fail2ban servisi yeniden başlatılacak. Yeni banlar 5-10 saniye duraklayabilir. Devam?',
        variant: 'warning',
        confirmText: 'Yeniden Başlat',
        cancelText: 'İptal',
    })
    if (! ok) return
    router.post(route('admin.fail2ban.restart'), {}, { preserveScroll: true })
}

const reloadFail2ban = () => {
    router.post(route('admin.fail2ban.reload'), {}, { preserveScroll: true })
}

// ── Template gallery filter ───────────────────────────────────────────────
const templateCategory = ref('all')
const templateSearch = ref('')

const filteredTemplates = computed(() => {
    let list = FAIL2BAN_TEMPLATES
    if (templateCategory.value === 'recommended') {
        list = list.filter(t => t.recommended)
    } else if (templateCategory.value !== 'all') {
        list = list.filter(t => t.category === templateCategory.value)
    }
    const q = templateSearch.value.trim().toLowerCase()
    if (q) {
        list = list.filter(t =>
            t.slug.toLowerCase().includes(q) ||
            t.display_name.toLowerCase().includes(q),
        )
    }
    return list
})

// ── Banned IP filter ──────────────────────────────────────────────────────
const banFilterJail = ref('')
const banSearch = ref('')

const filteredBans = computed(() => {
    let list = props.banned_ips || []
    if (banFilterJail.value) {
        list = list.filter(b => b.jail === banFilterJail.value)
    }
    const q = banSearch.value.trim().toLowerCase()
    if (q) {
        list = list.filter(b =>
            b.ip.includes(q) ||
            (b.country_code || '').toLowerCase().includes(q) ||
            (b.jail || '').toLowerCase().includes(q),
        )
    }
    return list
})

const uniqueJailsInBans = computed(() => {
    const set = new Set((props.banned_ips || []).map(b => b.jail))
    return [...set].sort()
})

// ── Helpers ───────────────────────────────────────────────────────────────
const formatNumber = (n) => (n || 0).toLocaleString('tr-TR')

const formatDuration = (seconds) => {
    if (! seconds) return '—'
    if (seconds < 60) return `${seconds}sn`
    if (seconds < 3600) return `${Math.floor(seconds / 60)}dk`
    if (seconds < 86400) return `${Math.floor(seconds / 3600)}sa`
    if (seconds < 604800) return `${Math.floor(seconds / 86400)}g`
    if (seconds < 2592000) return `${Math.floor(seconds / 604800)}hafta`
    return `${Math.floor(seconds / 2592000)}ay`
}

const formatRelative = (val) => {
    if (! val) return '—'
    const d = new Date(val)
    const seconds = Math.floor((Date.now() - d.getTime()) / 1000)
    if (seconds < 0) return `${Math.abs(Math.floor(seconds / 60))}dk içinde`
    if (seconds < 60) return `${seconds}sn önce`
    if (seconds < 3600) return `${Math.floor(seconds / 60)}dk önce`
    if (seconds < 86400) return `${Math.floor(seconds / 3600)}sa önce`
    return `${Math.floor(seconds / 86400)}g önce`
}

const severityColor = {
    high:   'bg-red-100 text-red-700 ring-red-300',
    medium: 'bg-amber-100 text-amber-700 ring-amber-300',
    low:    'bg-slate-100 text-slate-600 ring-slate-300',
}

const categoryColor = (cat) => {
    const c = TEMPLATE_CATEGORIES[cat]
    if (! c) return 'bg-slate-100 text-slate-600'
    const colors = {
        rose:    'bg-rose-100 text-rose-700 ring-rose-300',
        indigo:  'bg-indigo-100 text-indigo-700 ring-indigo-300',
        amber:   'bg-amber-100 text-amber-700 ring-amber-300',
        cyan:    'bg-cyan-100 text-cyan-700 ring-cyan-300',
        emerald: 'bg-emerald-100 text-emerald-700 ring-emerald-300',
        purple:  'bg-purple-100 text-purple-700 ring-purple-300',
        pink:    'bg-pink-100 text-pink-700 ring-pink-300',
        sky:     'bg-sky-100 text-sky-700 ring-sky-300',
        orange:  'bg-orange-100 text-orange-700 ring-orange-300',
        slate:   'bg-slate-100 text-slate-700 ring-slate-300',
    }
    return colors[c.color] || 'bg-slate-100 text-slate-700'
}

// Hourly chart max for relative bar heights
const maxHourlyBans = computed(() =>
    Math.max(1, ...(props.hourly_chart || []).map(h => h.bans))
)
</script>

<template>
    <Head title="fail2ban — Gelişmiş" />

    <AdminLayout>
        <template #header>fail2ban Gelişmiş Yönetim</template>

        <!-- Global status header -->
        <div class="mb-6 rounded-xl border border-slate-200 bg-white shadow-sm p-5">
            <div class="flex items-center justify-between flex-wrap gap-4">
                <div class="flex items-center gap-3">
                    <ShieldCheckIcon class="h-8 w-8 text-emerald-500" />
                    <div>
                        <h2 class="text-lg font-semibold flex items-center gap-2">
                            fail2ban
                            <span v-if="status?.running" class="inline-flex items-center gap-1 rounded-full bg-emerald-100 px-2 py-0.5 text-xs font-medium text-emerald-700">
                                <span class="h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse"></span>
                                Çalışıyor
                            </span>
                            <span v-else class="inline-flex items-center gap-1 rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-700">
                                <XCircleIcon class="h-3.5 w-3.5" />
                                Durduruldu
                            </span>
                        </h2>
                        <p class="text-xs text-slate-500">
                            v{{ status?.version || '?' }} ·
                            {{ status?.count || 0 }} jail aktif ·
                            Uptime: {{ formatDuration(status?.uptime_seconds) }}
                        </p>
                    </div>
                </div>

                <div class="flex gap-2">
                    <button @click="reloadFail2ban"
                            class="inline-flex items-center gap-2 rounded-lg border border-slate-300 px-3 py-2 text-sm font-medium hover:bg-slate-50">
                        <ArrowPathIcon class="h-4 w-4" />
                        Reload Config
                    </button>
                    <button @click="restartFail2ban"
                            class="inline-flex items-center gap-2 rounded-lg bg-amber-600 px-3 py-2 text-sm font-medium text-white hover:bg-amber-700">
                        <PowerIcon class="h-4 w-4" />
                        Restart
                    </button>
                </div>
            </div>
        </div>

        <!-- 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 — Genel Bakış (Dashboard)
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'dashboard'" class="space-y-6">

            <!-- Stat cards -->
            <div class="grid grid-cols-2 gap-4 lg:grid-cols-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">Aktif Ban</p>
                    <p class="text-3xl font-bold text-red-900">{{ formatNumber(stats?.currently_banned) }}</p>
                    <p class="text-xs text-red-600 mt-1">Şu an engelli IP</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">Bugün</p>
                    <p class="text-3xl font-bold text-amber-900">{{ formatNumber(stats?.today_bans) }}</p>
                    <p class="text-xs text-amber-600 mt-1">{{ formatNumber(stats?.today_failed) }} fail attempt</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">Bu Hafta</p>
                    <p class="text-3xl font-bold text-indigo-900">{{ formatNumber(stats?.week_bans) }}</p>
                    <p class="text-xs text-indigo-600 mt-1">Toplam ban</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">Bu Ay</p>
                    <p class="text-3xl font-bold text-purple-900">{{ formatNumber(stats?.month_bans) }}</p>
                    <p class="text-xs text-purple-600 mt-1">Toplam ban</p>
                </div>
            </div>

            <!-- 24h chart + Bans by jail -->
            <div class="grid grid-cols-1 gap-6 lg:grid-cols-2">

                <!-- 24h 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">Son 24 Saatte Banlar</h3>
                    </div>
                    <div v-if="! hourly_chart || hourly_chart.length === 0" class="py-8 text-center text-sm text-slate-500">
                        Henüz veri yok.
                    </div>
                    <div v-else class="flex items-end justify-between gap-1 h-48">
                        <div v-for="h in 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 transition">
                                {{ h.bans }}
                            </span>
                            <div :style="{ height: `${(h.bans / maxHourlyBans) * 100}%`, minHeight: '2px' }"
                                 class="w-full bg-indigo-500 hover:bg-indigo-600 rounded-t transition cursor-pointer"
                                 :title="`${h.hour}: ${h.bans} ban, ${h.failed} fail`">
                            </div>
                            <span class="text-[9px] text-slate-500">{{ h.hour }}</span>
                        </div>
                    </div>
                </div>

                <!-- Bans by jail -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm p-5">
                    <div class="flex items-center gap-2 mb-4">
                        <LockClosedIcon class="h-5 w-5 text-rose-500" />
                        <h3 class="text-base font-semibold">Jail Bazlı Ban Dağılımı</h3>
                    </div>
                    <div v-if="! bans_by_jail || bans_by_jail.length === 0" class="py-8 text-center text-sm text-slate-500">
                        Henüz veri yok.
                    </div>
                    <div v-else class="space-y-3">
                        <div v-for="b in bans_by_jail" :key="b.jail" class="flex items-center gap-3">
                            <span class="text-xs font-medium text-slate-700 w-32 truncate">{{ b.jail }}</span>
                            <div class="flex-1 h-5 bg-slate-100 rounded-full overflow-hidden">
                                <div :style="{ width: `${(b.count / Math.max(...bans_by_jail.map(x => x.count))) * 100}%` }"
                                     class="h-full bg-gradient-to-r from-indigo-500 to-purple-500"></div>
                            </div>
                            <span class="text-xs font-mono font-bold text-slate-800 w-12 text-right">{{ formatNumber(b.count) }}</span>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Top 10 attackers -->
            <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">
                    <NoSymbolIcon class="h-5 w-5 text-red-500" />
                    <h3 class="text-base font-semibold">Son 24 Saatin Top 10 Saldırgan IP'si</h3>
                </div>
                <div v-if="! top_attackers || top_attackers.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">
                    Henüz saldırı kaydı yok.
                </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">#</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-right">Deneme</th>
                                <th class="px-4 py-2 text-left">Durum</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="(a, i) in top_attackers" :key="i" class="hover:bg-slate-50">
                                <td class="px-4 py-2 text-xs text-slate-400">{{ i + 1 }}</td>
                                <td class="px-4 py-2 font-mono">{{ a.ip }}</td>
                                <td class="px-4 py-2">
                                    <span v-if="a.country_code" class="inline-flex items-center gap-1.5">
                                        <img :src="flagUrl(a.country_code)" :alt="a.country_code" class="w-5 h-3.5 rounded-sm" loading="lazy" />
                                        <span class="text-xs">{{ a.country_code }}</span>
                                    </span>
                                </td>
                                <td class="px-4 py-2 text-right font-mono font-bold text-red-600">{{ formatNumber(a.attempts) }}</td>
                                <td class="px-4 py-2">
                                    <span v-if="a.banned" class="inline-flex items-center gap-1 rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-700">
                                        <NoSymbolIcon class="h-3 w-3" />
                                        Banlı
                                    </span>
                                    <span v-else class="inline-flex items-center rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-700">
                                        İzleniyor
                                    </span>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

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

            <!-- Header -->
            <div class="flex items-center justify-between">
                <p class="text-sm text-slate-600">
                    <strong>{{ jails?.length || 0 }}</strong> aktif jail ·
                    <strong>{{ jails_meta?.length || 0 }}</strong> kayıtlı yapılandırma
                </p>
                <button @click="showJailForm = !showJailForm; if (!showJailForm) jailForm.reset()"
                        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">
                    <PlusIcon class="h-4 w-4" />
                    {{ showJailForm ? 'İptal' : 'Yeni Jail' }}
                </button>
            </div>

            <!-- Jail form (collapsible) -->
            <div v-if="showJailForm" class="rounded-xl border border-indigo-200 bg-indigo-50/50 p-5">
                <h3 class="font-semibold text-sm mb-4">Jail Yapılandırması</h3>
                <form @submit.prevent="submitJail" class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
                    <div>
                        <label class="block text-xs font-medium text-slate-700 mb-1">Jail Adı *</label>
                        <input v-model="jailForm.jail_name" required placeholder="sshd, panel-login"
                               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">Görünür İsim</label>
                        <input v-model="jailForm.display_name" placeholder="SSH (OpenSSH)"
                               class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                    </div>
                    <div>
                        <label class="block text-xs font-medium text-slate-700 mb-1">Port</label>
                        <input v-model="jailForm.port" placeholder="ssh,22"
                               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">Filter (boş = jail_name)</label>
                        <input v-model="jailForm.filter" placeholder="sshd"
                               class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                    </div>
                    <div class="md:col-span-2">
                        <label class="block text-xs font-medium text-slate-700 mb-1">Log Path</label>
                        <input v-model="jailForm.logpath" required placeholder="/var/log/secure"
                               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">Max Retry</label>
                        <input v-model.number="jailForm.maxretry" 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">Find Time (saniye)</label>
                        <input v-model.number="jailForm.findtime" type="number" min="30"
                               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">Ban Time (saniye)</label>
                        <input v-model.number="jailForm.bantime" type="number" min="60"
                               class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                    </div>
                    <div class="md:col-span-2">
                        <label class="block text-xs font-medium text-slate-700 mb-1">Action</label>
                        <input v-model="jailForm.action" placeholder="%(action_)s veya %(action_mwl)s"
                               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">Etkin</label>
                        <button type="button" @click="jailForm.enabled = !jailForm.enabled"
                                :class="['relative inline-flex h-6 w-11 items-center rounded-full transition mt-1.5', jailForm.enabled ? 'bg-emerald-600' : 'bg-slate-300']">
                            <span :class="['inline-block h-4 w-4 transform rounded-full bg-white transition', jailForm.enabled ? 'translate-x-6' : 'translate-x-1']"></span>
                        </button>
                    </div>
                    <div class="md:col-span-3">
                        <label class="block text-xs font-medium text-slate-700 mb-1">Açıklama (opsiyonel)</label>
                        <textarea v-model="jailForm.description" rows="2"
                                  class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"></textarea>
                    </div>
                    <div class="md:col-span-3 flex justify-end">
                        <button type="submit" :disabled="jailForm.processing"
                                class="inline-flex items-center gap-2 rounded-lg bg-emerald-600 px-5 py-2 text-sm font-semibold text-white hover:bg-emerald-700 disabled:opacity-50">
                            <CheckCircleIcon class="h-4 w-4" />
                            {{ jailForm.processing ? 'Kaydediliyor...' : 'Kaydet ve Reload' }}
                        </button>
                    </div>
                </form>
            </div>

            <!-- Active jails (live status) -->
            <div class="grid grid-cols-1 gap-4 lg:grid-cols-2">
                <div v-for="jail in jails" :key="jail.name"
                     class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
                    <div class="flex items-center justify-between mb-3">
                        <div class="flex items-center gap-2">
                            <LockClosedIcon class="h-5 w-5 text-indigo-500" />
                            <h4 class="text-base font-semibold">{{ jail.name }}</h4>
                        </div>
                        <span class="rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-800">
                            {{ jail.currently_banned || 0 }} aktif ban
                        </span>
                    </div>
                    <div class="grid grid-cols-2 gap-2 text-xs text-slate-600 mb-3">
                        <div>Toplam fail: <strong>{{ formatNumber(jail.total_failed) }}</strong></div>
                        <div>Toplam ban: <strong>{{ formatNumber(jail.total_banned) }}</strong></div>
                        <div>Aktif fail: <strong>{{ jail.currently_failed }}</strong></div>
                        <div>Aktif ban: <strong>{{ jail.currently_banned }}</strong></div>
                    </div>
                    <div v-if="jail.banned_ips?.length" class="mb-3">
                        <p class="text-xs font-medium text-slate-500 mb-1">Banlı IP'ler:</p>
                        <div class="flex flex-wrap gap-1">
                            <span v-for="ip in jail.banned_ips" :key="ip"
                                  class="inline-flex items-center gap-1 rounded bg-red-100 px-2 py-0.5 font-mono text-xs text-red-800 group">
                                {{ ip }}
                                <button @click="quickUnban(jail.name, ip)" class="opacity-50 hover:opacity-100" title="Unban">
                                    <XCircleIcon class="h-3 w-3" />
                                </button>
                            </span>
                        </div>
                    </div>
                    <div class="flex gap-2 pt-2 border-t border-slate-100">
                        <button @click="unbanAll(jail.name)"
                                class="flex-1 inline-flex items-center justify-center gap-1 rounded-lg border border-amber-200 bg-amber-50 px-2 py-1 text-xs text-amber-700 hover:bg-amber-100">
                            Tümünü Unban
                        </button>
                    </div>
                </div>
            </div>

            <!-- Managed jails (DB metadata) -->
            <div v-if="jails_meta && jails_meta.length" 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">Yapılandırılmış Jail'ler</h3>
                </div>
                <div 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">Jail</th>
                                <th class="px-4 py-2 text-left">Açıklama</th>
                                <th class="px-4 py-2 text-left">Limits</th>
                                <th class="px-4 py-2 text-left">Durum</th>
                                <th class="px-4 py-2 text-left">İşlem</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="jm in jails_meta" :key="jm.id" class="hover:bg-slate-50">
                                <td class="px-4 py-2">
                                    <div class="font-mono text-sm font-bold">{{ jm.jail_name }}</div>
                                    <div class="text-xs text-slate-500">{{ jm.display_name }}</div>
                                </td>
                                <td class="px-4 py-2 text-xs text-slate-600 max-w-xs truncate">{{ jm.description || '—' }}</td>
                                <td class="px-4 py-2 text-xs font-mono text-slate-500">
                                    {{ jm.maxretry }} fail / {{ formatDuration(jm.findtime) }} → {{ formatDuration(jm.bantime) }} ban
                                </td>
                                <td class="px-4 py-2">
                                    <button @click="toggleJail(jm.jail_name)"
                                            :class="['relative inline-flex h-5 w-9 items-center rounded-full transition', jm.is_enabled ? 'bg-emerald-600' : 'bg-slate-300']">
                                        <span :class="['inline-block h-3.5 w-3.5 transform rounded-full bg-white transition', jm.is_enabled ? 'translate-x-5' : 'translate-x-1']"></span>
                                    </button>
                                </td>
                                <td class="px-4 py-2">
                                    <div class="flex gap-1">
                                        <button @click="editJail(jm)" title="Düzenle"
                                                class="rounded p-1.5 text-slate-500 hover:bg-slate-100">
                                            <PencilIcon class="h-3.5 w-3.5" />
                                        </button>
                                        <button @click="deleteJail(jm.jail_name)" title="Sil"
                                                class="rounded p-1.5 text-red-500 hover:bg-red-50">
                                            <TrashIcon class="h-3.5 w-3.5" />
                                        </button>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 3 — Şablonlar (Template Gallery)
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'templates'" class="space-y-6">

            <div class="rounded-xl border border-purple-200 bg-purple-50 p-4 text-sm text-purple-900">
                <div class="flex gap-3">
                    <SparklesIcon class="h-5 w-5 flex-shrink-0 text-purple-600" />
                    <div>
                        <strong>{{ FAIL2BAN_TEMPLATES.length }} hazır jail şablonu:</strong> SSH, Apache, Nginx, Postfix, Dovecot,
                        FTP, MySQL, PostgreSQL, WordPress, phpMyAdmin, BIND, Asterisk ve daha fazlası.
                        Şablonu seç → form ön-doldurulur → ihtiyaca göre özelleştir → kaydet.
                    </div>
                </div>
            </div>

            <!-- Search + filter -->
            <div class="space-y-4">
                <div class="relative">
                    <MagnifyingGlassIcon class="absolute left-3 top-2.5 h-4 w-4 text-slate-400" />
                    <input v-model="templateSearch" type="search" placeholder="Şablon adı veya slug ile ara..."
                           class="w-full rounded-lg border border-slate-300 pl-9 pr-4 py-2 text-sm" />
                </div>
                <div class="flex flex-wrap gap-2">
                    <button @click="templateCategory = 'all'"
                            :class="['rounded-full px-3 py-1 text-xs font-medium transition', templateCategory === 'all' ? 'bg-indigo-600 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200']">
                        Tümü ({{ FAIL2BAN_TEMPLATES.length }})
                    </button>
                    <button @click="templateCategory = 'recommended'"
                            :class="['rounded-full px-3 py-1 text-xs font-medium transition flex items-center gap-1', templateCategory === 'recommended' ? 'bg-amber-600 text-white' : 'bg-amber-50 text-amber-700 hover:bg-amber-100']">
                        <StarIcon class="h-3 w-3" />
                        Önerilen ({{ FAIL2BAN_TEMPLATES.filter(t => t.recommended).length }})
                    </button>
                    <button v-for="cat in Object.values(TEMPLATE_CATEGORIES)" :key="cat.code"
                            @click="templateCategory = cat.code"
                            :class="['rounded-full px-3 py-1 text-xs font-medium transition', templateCategory === cat.code ? 'bg-indigo-600 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200']">
                        {{ cat.name }}
                    </button>
                </div>
            </div>

            <!-- Templates grid -->
            <div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
                <div v-for="t in filteredTemplates" :key="t.slug"
                     class="rounded-xl border border-slate-200 bg-white shadow-sm p-5 hover:border-indigo-300 hover:shadow-md transition">
                    <div class="flex items-start justify-between mb-2">
                        <div class="flex-1 min-w-0">
                            <div class="flex items-center gap-2">
                                <h4 class="text-base font-semibold truncate">{{ t.display_name }}</h4>
                                <StarIcon v-if="t.recommended" class="h-4 w-4 text-amber-500 fill-amber-500 flex-shrink-0" />
                            </div>
                            <p class="text-[10px] font-mono text-slate-500">{{ t.slug }}</p>
                        </div>
                        <span :class="['rounded-full px-2 py-0.5 text-[10px] font-semibold ring-1', categoryColor(t.category)]">
                            {{ TEMPLATE_CATEGORIES[t.category]?.name }}
                        </span>
                    </div>

                    <p class="text-xs text-slate-600 mb-3 line-clamp-2 min-h-[2rem]">{{ t.description }}</p>

                    <div class="grid grid-cols-2 gap-x-3 gap-y-1 text-[10px] mb-3 pb-3 border-b border-slate-100">
                        <div class="text-slate-500">Port: <span class="font-mono text-slate-700">{{ t.port }}</span></div>
                        <div class="text-slate-500">Retry: <span class="font-mono text-slate-700">{{ t.maxretry }}</span></div>
                        <div class="text-slate-500">Find: <span class="font-mono text-slate-700">{{ formatDuration(t.findtime) }}</span></div>
                        <div class="text-slate-500">Ban: <span class="font-mono text-slate-700">{{ formatDuration(t.bantime) }}</span></div>
                    </div>

                    <div class="flex items-center justify-between gap-2">
                        <span :class="['inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium ring-1', severityColor[t.severity]]">
                            {{ t.severity === 'high' ? 'Yüksek Öncelik' : t.severity === 'medium' ? 'Orta' : 'Düşük' }}
                        </span>
                        <button @click="applyTemplate(t)"
                                class="inline-flex items-center gap-1 rounded-lg bg-indigo-600 px-3 py-1 text-xs font-medium text-white hover:bg-indigo-700">
                            <PlusIcon class="h-3 w-3" />
                            Kullan
                        </button>
                    </div>
                </div>
            </div>

            <div v-if="filteredTemplates.length === 0" class="rounded-xl border border-slate-200 bg-slate-50 p-12 text-center text-sm text-slate-500">
                Eşleşen şablon bulunamadı.
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 4 — Banlı IP'ler (Consolidated)
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'banned'" class="space-y-6">

            <!-- Filter + bulk ban -->
            <div class="grid grid-cols-1 gap-6 lg:grid-cols-3">

                <!-- Filter -->
                <div class="rounded-xl border border-slate-200 bg-white shadow-sm p-5 lg:col-span-2">
                    <h3 class="text-base font-semibold mb-3">Filtrele</h3>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <div class="relative">
                            <MagnifyingGlassIcon class="absolute left-3 top-2.5 h-4 w-4 text-slate-400" />
                            <input v-model="banSearch" placeholder="IP, ülke veya jail ara..."
                                   class="w-full rounded-lg border border-slate-300 pl-9 pr-3 py-2 text-sm" />
                        </div>
                        <select v-model="banFilterJail"
                                class="rounded-lg border border-slate-300 px-3 py-2 text-sm">
                            <option value="">Tüm jail'ler</option>
                            <option v-for="j in uniqueJailsInBans" :key="j" :value="j">{{ j }}</option>
                        </select>
                    </div>
                    <p class="text-xs text-slate-500 mt-3">
                        <strong>{{ filteredBans.length }}</strong> ban gösteriliyor (toplam: {{ banned_ips?.length || 0 }})
                    </p>
                </div>

                <!-- Manual ban -->
                <div class="rounded-xl border border-red-200 bg-red-50 p-5">
                    <h3 class="text-base font-semibold mb-3 flex items-center gap-2 text-red-900">
                        <NoSymbolIcon class="h-5 w-5" /> Manuel Ban
                    </h3>
                    <form @submit.prevent="ban" class="space-y-2">
                        <input v-model="banForm.jail" placeholder="jail" required
                               class="w-full rounded border border-red-300 px-3 py-2 text-sm" />
                        <input v-model="banForm.ip" placeholder="1.2.3.4" required
                               class="w-full rounded border border-red-300 px-3 py-2 font-mono text-sm" />
                        <input v-model="banForm.comment" placeholder="Açıklama (opsiyonel)"
                               class="w-full rounded border border-red-300 px-3 py-2 text-sm" />
                        <button class="w-full rounded bg-red-600 px-3 py-2 text-sm font-semibold text-white hover:bg-red-700">
                            Banla
                        </button>
                    </form>
                </div>
            </div>

            <!-- Bulk ban -->
            <div class="rounded-xl border border-amber-200 bg-amber-50 p-5">
                <h3 class="text-base font-semibold mb-3 flex items-center gap-2 text-amber-900">
                    <UserGroupIcon class="h-5 w-5" /> Toplu Ban (paste IP listesi)
                </h3>
                <div class="grid grid-cols-1 md:grid-cols-4 gap-3 items-start">
                    <div class="md:col-span-3">
                        <textarea v-model="bulkBanText" rows="4"
                                  placeholder="Her satıra bir IP. Örnek:&#10;1.2.3.4&#10;5.6.7.8&#10;10.0.0.0/24"
                                  class="w-full rounded-lg border border-amber-300 px-3 py-2 font-mono text-xs"></textarea>
                    </div>
                    <div class="space-y-2">
                        <select v-model="bulkBanJail" class="w-full rounded-lg border border-amber-300 px-3 py-2 text-sm">
                            <option v-for="j in (status?.jails || ['sshd'])" :key="j" :value="j">{{ j }}</option>
                        </select>
                        <button @click="doBulkBan" :disabled="bulkBanRunning"
                                class="w-full rounded bg-amber-600 px-3 py-2 text-sm font-semibold text-white hover:bg-amber-700 disabled:opacity-50">
                            {{ bulkBanRunning ? 'Banlanıyor...' : `Tümünü Banla` }}
                        </button>
                    </div>
                </div>
            </div>

            <!-- Banned IPs table -->
            <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 justify-between">
                    <h3 class="text-base font-semibold">Aktif Banlar (Tüm Jail'ler)</h3>
                </div>
                <div v-if="filteredBans.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">
                    Eşleşen ban yok.
                </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">IP</th>
                                <th class="px-4 py-2 text-left">Ülke</th>
                                <th class="px-4 py-2 text-left">Jail</th>
                                <th class="px-4 py-2 text-right">Fail</th>
                                <th class="px-4 py-2 text-left">Banlanma</th>
                                <th class="px-4 py-2 text-left">Bitiş</th>
                                <th class="px-4 py-2 text-left">İşlem</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-slate-100">
                            <tr v-for="(b, i) in filteredBans" :key="i" class="hover:bg-slate-50">
                                <td class="px-4 py-2 font-mono">{{ b.ip }}</td>
                                <td class="px-4 py-2">
                                    <span v-if="b.country_code" class="inline-flex items-center gap-1.5">
                                        <img :src="flagUrl(b.country_code)" :alt="b.country_code" class="w-5 h-3.5 rounded-sm" loading="lazy" />
                                        <span class="text-xs">{{ b.country_code }}</span>
                                    </span>
                                </td>
                                <td class="px-4 py-2">
                                    <span class="inline-flex items-center rounded-full bg-indigo-100 px-2 py-0.5 text-xs font-medium text-indigo-700">
                                        {{ b.jail }}
                                    </span>
                                </td>
                                <td class="px-4 py-2 text-right font-mono text-red-600">{{ formatNumber(b.failed_attempts) }}</td>
                                <td class="px-4 py-2 text-xs text-slate-500">{{ formatRelative(b.banned_at) }}</td>
                                <td class="px-4 py-2 text-xs text-slate-500">{{ formatRelative(b.expires_at) }}</td>
                                <td class="px-4 py-2">
                                    <button @click="quickUnban(b.jail, b.ip)"
                                            class="inline-flex items-center gap-1 rounded border border-emerald-200 bg-emerald-50 px-2 py-1 text-xs text-emerald-700 hover:bg-emerald-100">
                                        <CheckCircleIcon class="h-3 w-3" />
                                        Unban
                                    </button>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 5 — 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">
                <div class="flex gap-3">
                    <ShieldCheckIcon class="h-5 w-5 flex-shrink-0 text-emerald-600" />
                    <div>
                        <strong>fail2ban İzin Listesi (ignoreip):</strong> Bu IP'ler hiçbir jail'de banlanmaz.
                        Ofis IP'leri, monitoring servisleri, partner IP'leri için kullanın.
                    </div>
                </div>
            </div>

            <!-- Add form -->
            <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">İzin Listesine Ekle</h3>
                </div>
                <form @submit.prevent="submitWhitelist" class="grid grid-cols-1 md:grid-cols-3 gap-4 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.label" placeholder="Etiket: Ofis, Pingdom, vb."
                           class="rounded-lg border border-slate-300 px-3 py-2 text-sm" maxlength="100" />
                    <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>

            <!-- List -->
            <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">İzin Listesi ({{ whitelist?.length || 0 }})</h3>
                </div>
                <div v-if="! whitelist || whitelist.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">
                    Henüz IP eklenmemiş.
                </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">Etiket</th>
                            <th class="px-4 py-2 text-left">Açıklama</th>
                            <th class="px-4 py-2 text-left">Eklenme</th>
                            <th class="px-4 py-2 text-left">İşlem</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">{{ w.label || '—' }}</td>
                            <td class="px-4 py-2 text-xs text-slate-500">{{ w.comment || '—' }}</td>
                            <td class="px-4 py-2 text-xs text-slate-500">{{ formatRelative(w.created_at) }}</td>
                            <td class="px-4 py-2">
                                <button @click="removeWhitelist(w.id, w.ip_or_cidr)"
                                        class="rounded border border-red-200 bg-red-50 px-2 py-1 text-xs text-red-600 hover:bg-red-100">
                                    <TrashIcon class="h-3.5 w-3.5 inline" />
                                    Sil
                                </button>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 6 — Ayarlar (Global Config + Presets)
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'settings'" class="space-y-6">

            <!-- Quick presets -->
            <div class="rounded-xl border border-slate-200 bg-white shadow-sm p-5">
                <h3 class="text-base font-semibold mb-3 flex items-center gap-2">
                    <SparklesIcon class="h-5 w-5 text-amber-500" />
                    Hızlı Presetler
                </h3>
                <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
                    <button v-for="(p, key) in PRESETS" :key="key" @click="applyPreset(key)"
                            :class="[
                                'text-left rounded-xl border-2 p-4 transition',
                                settings?.preset_mode === key
                                    ? `border-${p.color}-500 bg-${p.color}-50`
                                    : 'border-slate-200 hover:border-slate-300'
                            ]">
                        <div class="flex items-center justify-between mb-2">
                            <h4 :class="`text-${p.color}-700 font-semibold`">{{ p.name }}</h4>
                            <CheckCircleIcon v-if="settings?.preset_mode === key" :class="`h-5 w-5 text-${p.color}-500`" />
                        </div>
                        <p class="text-xs text-slate-600">{{ p.description }}</p>
                        <div class="mt-2 pt-2 border-t border-slate-100 text-[10px] text-slate-500 font-mono">
                            {{ p.default_maxretry }} retry · {{ formatDuration(p.default_findtime) }} → {{ formatDuration(p.default_bantime) }} ban
                        </div>
                    </button>
                </div>
            </div>

            <!-- Manual settings -->
            <form @submit.prevent="submitSettings" class="space-y-6">

                <!-- Defaults -->
                <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">Varsayılan Jail Ayarları</h3>
                    </div>
                    <div class="grid grid-cols-1 md:grid-cols-3 gap-4 p-5">
                        <div>
                            <label class="block text-xs font-medium text-slate-700 mb-1">Default Max Retry</label>
                            <input v-model.number="settingsForm.default_maxretry" 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 Find Time (sn)</label>
                            <input v-model.number="settingsForm.default_findtime" type="number" min="30"
                                   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 Ban Time (sn)</label>
                            <input v-model.number="settingsForm.default_bantime" type="number" min="60"
                                   class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                        </div>
                        <div class="md:col-span-3">
                            <label class="block text-xs font-medium text-slate-700 mb-1">Default Action</label>
                            <input v-model="settingsForm.default_action"
                                   class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm" />
                        </div>
                    </div>
                </div>

                <!-- Notifications -->
                <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">Bildirimler</h3>
                    </div>
                    <div class="divide-y divide-slate-100">
                        <div class="flex items-center justify-between px-5 py-4">
                            <div>
                                <div class="font-medium text-sm">Ban Olduğunda E-posta Gönder</div>
                                <p class="text-xs text-slate-500">Her ban olayında destemail adresine bildirim</p>
                            </div>
                            <button type="button" @click="settingsForm.notify_on_ban = !settingsForm.notify_on_ban"
                                    :class="['relative inline-flex h-6 w-11 items-center rounded-full transition', settingsForm.notify_on_ban ? 'bg-indigo-600' : 'bg-slate-300']">
                                <span :class="['inline-block h-4 w-4 transform rounded-full bg-white transition', settingsForm.notify_on_ban ? 'translate-x-6' : 'translate-x-1']"></span>
                            </button>
                        </div>
                        <div class="grid grid-cols-1 md:grid-cols-2 gap-4 px-5 py-4">
                            <div>
                                <label class="block text-xs font-medium text-slate-700 mb-1">Destination E-posta</label>
                                <input v-model="settingsForm.destemail" type="email"
                                       class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                            </div>
                            <div>
                                <label class="block text-xs font-medium text-slate-700 mb-1">Sender (From)</label>
                                <input v-model="settingsForm.sender"
                                       class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm" />
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Recidive -->
                <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">Recidive (Tekrarcı Bans)</h3>
                    </div>
                    <div class="flex items-center justify-between px-5 py-4">
                        <div>
                            <div class="font-medium text-sm">Recidive Jail Aktif</div>
                            <p class="text-xs text-slate-500">Birden fazla jail'de banlanan IP'leri 1 hafta engelle</p>
                        </div>
                        <button type="button" @click="settingsForm.recidive_enabled = !settingsForm.recidive_enabled"
                                :class="['relative inline-flex h-6 w-11 items-center rounded-full transition', settingsForm.recidive_enabled ? 'bg-red-600' : 'bg-slate-300']">
                            <span :class="['inline-block h-4 w-4 transform rounded-full bg-white transition', settingsForm.recidive_enabled ? 'translate-x-6' : 'translate-x-1']"></span>
                        </button>
                    </div>
                </div>

                <!-- Database -->
                <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">Veritabanı & Loglama</h3>
                    </div>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-4 p-5">
                        <div>
                            <label class="block text-xs font-medium text-slate-700 mb-1">DB Purge Age (sn)</label>
                            <input v-model.number="settingsForm.dbpurgeage" type="number" min="60"
                                   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">DB Max Matches</label>
                            <input v-model.number="settingsForm.dbmaxmatches" 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">Log Target</label>
                            <input v-model="settingsForm.logtarget"
                                   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">Log Level</label>
                            <select v-model="settingsForm.loglevel" class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm">
                                <option>DEBUG</option><option>INFO</option><option>NOTICE</option>
                                <option>WARNING</option><option>ERROR</option><option>CRITICAL</option>
                            </select>
                        </div>
                    </div>
                </div>

                <div class="flex justify-end rounded-xl border border-slate-200 bg-white p-3 shadow-sm">
                    <button type="submit" 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">
                        <CheckCircleIcon class="h-5 w-5" />
                        Kaydet ve Yeniden Başlat
                    </button>
                </div>
            </form>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 7 — Filter Test
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'filters'" class="space-y-6">

            <div class="rounded-xl border border-cyan-200 bg-cyan-50 p-4 text-sm text-cyan-900">
                <div class="flex gap-3">
                    <BeakerIcon class="h-5 w-5 flex-shrink-0 text-cyan-600" />
                    <div>
                        <strong>Filter Test Aracı:</strong> Bir fail2ban filter'ının (failregex) belirli bir log satırını
                        eşleştirip eşleştirmediğini kontrol eder. Yeni jail yapılandırırken çok kullanışlı.
                        Backend: <code class="font-mono">fail2ban-regex</code>.
                    </div>
                </div>
            </div>

            <!-- Test form -->
            <div class="rounded-xl border border-slate-200 bg-white shadow-sm">
                <div class="border-b border-slate-200 px-5 py-3 flex items-center gap-2">
                    <BeakerIcon class="h-5 w-5 text-cyan-500" />
                    <h3 class="text-base font-semibold">Filter Test</h3>
                </div>
                <form @submit.prevent="doFilterTest" class="space-y-4 p-5">
                    <div>
                        <label class="block text-xs font-medium text-slate-700 mb-1">Filter Adı</label>
                        <select v-model="filterTestForm.filter" class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-sm">
                            <option v-for="f in (available_filters || [])" :key="f" :value="f">{{ f }}</option>
                        </select>
                    </div>
                    <div>
                        <label class="block text-xs font-medium text-slate-700 mb-1">Test Edilecek Log Satırı</label>
                        <textarea v-model="filterTestForm.log_line" rows="3"
                                  class="w-full rounded-lg border border-slate-300 px-3 py-2 font-mono text-xs"></textarea>
                    </div>
                    <button type="submit" :disabled="filterTesting"
                            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" />
                        {{ filterTesting ? 'Test ediliyor…' : 'Filter\'ı Test Et' }}
                    </button>
                </form>
            </div>

            <!-- Result -->
            <div v-if="filterTestResult" class="rounded-xl border bg-white shadow-sm"
                 :class="filterTestResult.matches > 0 ? 'border-emerald-300' : 'border-amber-300'">
                <div class="border-b px-5 py-3 flex items-center justify-between"
                     :class="filterTestResult.matches > 0 ? 'border-emerald-100 bg-emerald-50' : 'border-amber-100 bg-amber-50'">
                    <h3 class="text-base font-semibold flex items-center gap-2">
                        <CheckCircleIcon v-if="filterTestResult.matches > 0" class="h-5 w-5 text-emerald-600" />
                        <XCircleIcon v-else class="h-5 w-5 text-amber-600" />
                        Sonuç: {{ filterTestResult.matches > 0 ? `${filterTestResult.matches} eşleşme` : 'Eşleşme yok' }}
                    </h3>
                    <span class="text-xs"
                          :class="filterTestResult.failregex_ok ? 'text-emerald-700' : 'text-amber-700'">
                        failregex syntax: {{ filterTestResult.failregex_ok ? 'OK' : 'HATA' }}
                    </span>
                </div>
                <div v-if="filterTestResult.matched_lines?.length" class="p-5">
                    <p class="text-xs font-medium text-slate-700 mb-2">Eşleşen satırlar:</p>
                    <pre class="bg-slate-50 rounded-lg p-3 text-[10px] font-mono whitespace-pre-wrap max-h-60 overflow-y-auto">{{ filterTestResult.matched_lines.join('\n') }}</pre>
                </div>
            </div>
        </div>

        <!-- ═══════════════════════════════════════════════════════════════
             TAB 8 — Geçmiş
        ════════════════════════════════════════════════════════════════════ -->
        <div v-if="activeTab === 'history'" class="space-y-6">

            <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">
                    <ClockIcon class="h-5 w-5 text-slate-500" />
                    <h3 class="text-base font-semibold">Ban / Unban Olay Geçmişi (Son 100)</h3>
                </div>
                <div v-if="! history || history.length === 0" class="px-5 py-12 text-center text-sm text-slate-500">
                    Henüz olay kaydı 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">Zaman</th>
                            <th class="px-4 py-2 text-left">Jail</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">Aksiyon</th>
                            <th class="px-4 py-2 text-left">Sebep</th>
                        </tr>
                    </thead>
                    <tbody class="divide-y divide-slate-100">
                        <tr v-for="ev in history" :key="ev.id" class="hover:bg-slate-50">
                            <td class="px-4 py-2 text-xs text-slate-500">{{ formatRelative(ev.event_at) }}</td>
                            <td class="px-4 py-2">
                                <span class="inline-flex items-center rounded-full bg-indigo-100 px-2 py-0.5 text-xs font-medium text-indigo-700">
                                    {{ ev.jail }}
                                </span>
                            </td>
                            <td class="px-4 py-2 font-mono text-xs">{{ ev.ip }}</td>
                            <td class="px-4 py-2">
                                <span v-if="ev.country_code" class="inline-flex items-center gap-1.5">
                                    <img :src="flagUrl(ev.country_code)" :alt="ev.country_code" class="w-4 h-3 rounded-sm" loading="lazy" />
                                    <span class="text-xs">{{ ev.country_code }}</span>
                                </span>
                            </td>
                            <td class="px-4 py-2">
                                <span :class="[
                                    'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',
                                    ev.action === 'banned' ? 'bg-red-100 text-red-700'
                                        : ev.action === 'unbanned' ? 'bg-emerald-100 text-emerald-700'
                                        : 'bg-slate-100 text-slate-700'
                                ]">
                                    {{ ev.action }}
                                </span>
                            </td>
                            <td class="px-4 py-2 text-xs text-slate-500">{{ ev.reason || ev.comment || '—' }}</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

    </AdminLayout>
</template>
