<script setup>
import {
    NFlex, NButton, NDataTable, NTag, NText, NEl, NIcon, NInput, NTooltip, NScrollbar, NGrid, NGi,
    NSwitch, NPopconfirm,
} from 'naive-ui'
import {
    TbRefresh, TbPlayerPlay, TbLayoutDashboard, TbAlertTriangle, TbBolt, TbTrash, TbPlus,
} from 'vue-icons-plus/tb'
import AppLayout from '../../../Layouts/AppLayout.vue'
import AppContainer from '../../../Components/AppContainer.vue'
import SectionCard from '../../../Components/SectionCard.vue'
import PageBanner from '../../../Components/PageBanner.vue'
import { Link, router, usePage } from '@inertiajs/vue3'
import { ref, computed, watch, h } from 'vue'
import { format } from 'date-fns'

const props = defineProps({
    logs: { type: Array, default: () => [] },
    schedules: { type: Array, default: () => [] },
    configured: { type: Boolean, default: false },
})

const page = usePage()
const running = ref(null)
const customId = ref('')

watch(() => page.props.flash, (f) => {
    if (f?.success) window.$message?.success(f.success)
    if (f?.error) window.$message?.error(f.error)
}, { deep: true })

function run(scheduleId) {
    const id = String(scheduleId ?? '').trim()
    if (!id) return
    running.value = id
    router.post('/admin/replication/run', { schedule_id: id }, {
        preserveScroll: true,
        onFinish: () => { running.value = null },
    })
}

// --- Управление расписаниями (таблица replication_schedules) ---
const newId = ref('')
const newName = ref('')

function addSchedule() {
    const id = newId.value.trim()
    if (!id) return
    router.post('/admin/replication/schedules', { schedule_id: id, name: newName.value.trim() || null }, {
        preserveScroll: true,
        onSuccess: () => { newId.value = ''; newName.value = '' },
    })
}

function toggleSchedule(s, value) {
    router.put(`/admin/replication/schedules/${s.id}`, { name: s.name, is_active: value }, {
        preserveScroll: true,
    })
}

function removeSchedule(s) {
    router.delete(`/admin/replication/schedules/${s.id}`, { preserveScroll: true })
}

const statusType = (s) => ({ success: 'success', partial_success: 'warning', failed: 'error' }[s] ?? 'default')
const statusLabel = (s) => ({ success: 'Успешно', partial_success: 'Частично', failed: 'Ошибка' }[s] ?? (s ?? '—'))
const fmt = (iso) => iso ? format(new Date(iso), 'dd.MM.yyyy HH:mm:ss') : '—'

const hasSchedules = computed(() => props.schedules.length > 0)
const lastLog = computed(() => props.logs[0] ?? null)

const columns = computed(() => [
    {
        key: 'received_at',
        title: 'Время',
        width: 170,
        render: (row) => h(NText, { style: 'font-size: 13px;' }, () => fmt(row.received_at)),
    },
    {
        key: 'status',
        title: 'Статус',
        width: 120,
        render: (row) => h(NTag, { type: statusType(row.status), size: 'small', round: true, bordered: false }, () => statusLabel(row.status)),
    },
    {
        key: 'schedule_id',
        title: 'Расписание',
        render: (row) => h(NText, { style: 'font-size: 13px; font-family: monospace;' }, () => row.schedule_id ?? '—'),
    },
    {
        key: 'tables_success',
        title: 'Таблиц ОК',
        width: 110,
        align: 'center',
        render: (row) => h(NTag, { size: 'small', round: true, bordered: false, type: 'success' }, () => `${row.tables_success}`),
    },
    {
        key: 'tables_failed',
        title: 'Ошибок',
        width: 100,
        align: 'center',
        render: (row) => h(NTag, {
            size: 'small', round: true, bordered: false,
            type: row.tables_failed > 0 ? 'error' : 'default',
        }, () => `${row.tables_failed}`),
    },
    {
        key: 'errors',
        title: 'Детали ошибок',
        width: 150,
        render: (row) => {
            if (!row.errors || !row.errors.length) return h(NText, { depth: 3 }, () => '—')
            return h(NTooltip, { style: { maxWidth: '440px' } }, {
                trigger: () => h(NTag, { type: 'error', size: 'small', round: true, bordered: false }, () => `${row.errors.length} ошиб.`),
                default: () => h(NScrollbar, { style: 'max-height: 240px;' },
                    () => row.errors.map((e, i) => h('div', { key: i, style: 'font-size: 12px; padding: 2px 0;' },
                        typeof e === 'string' ? e : JSON.stringify(e)))),
            })
        },
    },
])
</script>

<template>
    <AppLayout>
        <AppContainer>

            <PageBanner
                title="Репликация"
                :icon="TbRefresh"
                :breadcrumbs="[{ label: 'Администратор', href: '/admin', icon: TbLayoutDashboard, tag: Link }]"
            >
                <template #meta>
                    <NFlex align="center" :size="8">
                        <NText depth="3" style="font-size: 13px;">{{ logs.length }} записей</NText>
                        <template v-if="lastLog">
                            <NEl style="width: 3px; height: 3px; border-radius: 50%; background: currentColor; opacity: .3;" />
                            <NText depth="3" style="font-size: 13px;">последняя:</NText>
                            <NTag :type="statusType(lastLog.status)" size="small" round :bordered="false">
                                {{ statusLabel(lastLog.status) }}
                            </NTag>
                        </template>
                    </NFlex>
                </template>
            </PageBanner>

            <!-- Запуск: 2 колонки — ручной запуск и шорткаты -->
            <NGrid cols="2" :x-gap="16">
                <NGi>
                    <SectionCard :icon="TbPlayerPlay" title="Запуск репликации">
                        <div v-if="!configured" class="hint-error">
                            <NIcon :component="TbAlertTriangle" /> Не задан <code>SYNCIO_BASE_URL</code> — запуск недоступен. Добавьте переменные окружения репликатора.
                        </div>
                        <NFlex v-else align="center" :size="8" :wrap="false">
                            <NInput v-model:value="customId" placeholder="schedule_id" clearable />
                            <NButton
                                type="primary"
                                :loading="running !== null && running === customId.trim() && customId.trim() !== ''"
                                :disabled="running !== null || !customId.trim()"
                                @click="run(customId)"
                            >
                                Запустить
                            </NButton>
                        </NFlex>
                    </SectionCard>
                </NGi>

                <NGi>
                    <SectionCard :icon="TbBolt" title="Шорткаты (расписания проекта)">
                        <NFlex vertical :size="8">
                            <NFlex
                                v-for="s in schedules" :key="s.id"
                                align="center" :size="8" :wrap="false"
                            >
                                <NButton
                                    type="primary" secondary
                                    :loading="running === s.schedule_id"
                                    :disabled="!configured || running !== null || !s.is_active"
                                    style="flex: 1; justify-content: flex-start;"
                                    @click="run(s.schedule_id)"
                                >
                                    <template #icon><NIcon><TbPlayerPlay /></NIcon></template>
                                    {{ s.name || s.schedule_id }}
                                </NButton>
                                <NTooltip>
                                    <template #trigger>
                                        <NSwitch :value="s.is_active" size="small" @update:value="v => toggleSchedule(s, v)" />
                                    </template>
                                    Учитывать вебхуки этого расписания
                                </NTooltip>
                                <NPopconfirm @positive-click="removeSchedule(s)">
                                    <template #trigger>
                                        <NButton text type="error" title="Удалить">
                                            <template #icon><NIcon><TbTrash /></NIcon></template>
                                        </NButton>
                                    </template>
                                    Удалить расписание «{{ s.name || s.schedule_id }}»?
                                </NPopconfirm>
                            </NFlex>

                            <NText v-if="!hasSchedules" depth="3" style="font-size: 12px;">
                                Расписаний нет. Добавьте ID расписания из репликатора ниже.
                            </NText>

                            <!-- Добавление -->
                            <NFlex align="center" :size="8" :wrap="false" style="margin-top: 4px;">
                                <NInput v-model:value="newId" placeholder="schedule_id" size="small" />
                                <NInput v-model:value="newName" placeholder="Имя" size="small" style="max-width: 150px;" />
                                <NButton size="small" :disabled="!newId.trim()" @click="addSchedule">
                                    <template #icon><NIcon><TbPlus /></NIcon></template>
                                </NButton>
                            </NFlex>
                        </NFlex>
                    </SectionCard>
                </NGi>
            </NGrid>

            <!-- История -->
            <SectionCard :icon="TbRefresh" title="История репликаций" no-padding style="margin-top: 12px;">
                <template #header-extra>
                    <NButton text size="small" @click="router.reload({ only: ['logs'] })">
                        <template #icon><NIcon><TbRefresh /></NIcon></template>
                        Обновить
                    </NButton>
                </template>
                <NDataTable
                    :columns="columns"
                    :data="logs"
                    :bordered="false"
                    size="small"
                    :max-height="520"
                />
            </SectionCard>

        </AppContainer>
    </AppLayout>
</template>

<style scoped>
.hint-error {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--error-color);
    font-size: 13px;
}
.hint-error code {
    background: color-mix(in srgb, var(--error-color) 12%, transparent);
    padding: 1px 5px;
    border-radius: 4px;
}

:deep(.n-data-table-th) { background: transparent !important; }
:deep(.n-data-table) { background: transparent; }
:deep(.n-data-table-wrapper) { border-radius: 0; }
:deep(.n-data-table-th .n-data-table-th__title) { font-size: 12px; }
:deep(.n-data-table-td) { font-size: 13px; }
</style>
