<script setup lang="ts">
/**
 * Универсальный экран ошибки для 404 / 403 / 500. Конфигурация через
 * `route.meta.errorCode` ('404' | '403' | '500').
 *
 * Источник дизайна: liderra_v8_handoff/concepts/v8_errors.html.
 *
 * Layout: meta.layout='error' — AppShell рендерит ErrorView напрямую без
 * AppLayout/AuthLayout (full-bleed теало-нуар bg + центрированный card).
 *
 * Не входит в этот коммит:
 * - Реальный requestId/incidentId из backend (сейчас mock).
 * - Status-pills из API /api/health (сейчас static на 500).
 * - Sentry capture при mount 500 (для production).
 */
import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';

interface ErrorConfig {
    code: '404' | '403' | '500';
    title: string;
    description: string;
    primaryAction: { label: string; icon: string; to?: string; onClick?: () => void };
    secondaryAction?: { label: string; icon: string; to?: string; href?: string; onClick?: () => void };
    showRequestId?: boolean;
    requestIdLabel?: string;
    requestId?: string;
    showStatusList?: boolean;
}

const route = useRoute();
const router = useRouter();

const errorCode = computed<'404' | '403' | '500'>(
    () => (route.meta.errorCode as '404' | '403' | '500' | undefined) ?? '404',
);

const config = computed<ErrorConfig>(() => {
    if (errorCode.value === '403') {
        return {
            code: '403',
            title: 'У вас нет доступа',
            description:
                'Эта страница принадлежит другому тенанту, либо ваша роль не позволяет её увидеть. Если вы считаете, что это ошибка — обратитесь к администратору вашей команды или в поддержку.',
            primaryAction: {
                label: 'На дашборд',
                icon: 'mdi-view-dashboard-outline',
                to: '/dashboard',
            },
            secondaryAction: {
                label: 'Написать в поддержку',
                icon: 'mdi-email-outline',
                href: 'mailto:support@liderra.app',
            },
            showRequestId: true,
            requestIdLabel: 'Запрос',
            requestId: 'REQ-3F8A2-0007',
        };
    }
    if (errorCode.value === '500') {
        return {
            code: '500',
            title: 'Что-то пошло не так',
            description:
                'Внутренняя ошибка — мы уже занимаемся. Команда получила уведомление. Большинство сбоев чинятся за 5–10 минут. Можно вернуться через минуту, или открыть страницу статуса.',
            primaryAction: {
                label: 'Попробовать снова',
                icon: 'mdi-refresh',
                onClick: () => location.reload(),
            },
            secondaryAction: {
                label: 'Статус сервиса',
                icon: 'mdi-pulse',
                href: 'https://status.liderra.app',
            },
            showRequestId: true,
            requestIdLabel: 'Инцидент',
            requestId: 'INC-2026-0507-0034',
            showStatusList: true,
        };
    }
    // default 404
    return {
        code: '404',
        title: 'Страница не найдена',
        description:
            'Похоже, такой страницы нет — её удалили, переименовали или вы ввели адрес с опечаткой. Все рабочие экраны Лидерра доступны через дашборд.',
        primaryAction: {
            label: 'На дашборд',
            icon: 'mdi-view-dashboard-outline',
            to: '/dashboard',
        },
        secondaryAction: {
            label: 'Назад',
            icon: 'mdi-arrow-left',
            onClick: () => router.back(),
        },
    };
});

const statusList = [
    { name: 'API', status: 'ok' },
    { name: 'Telegram', status: 'degraded' },
    { name: 'YooKassa', status: 'ok' },
];

async function copyRequestId() {
    if (config.value.requestId) {
        await navigator.clipboard.writeText(config.value.requestId);
    }
}

function statusColor(s: string): string {
    return s === 'ok' ? '#2E8B57' : s === 'degraded' ? '#D9A441' : '#B83A3A';
}
</script>

<template>
    <v-app>
        <v-main class="error-main">
            <a class="top-brand" href="/" aria-label="На главную">
                <span class="mark" aria-hidden="true">
                    <svg viewBox="0 0 48 48" width="22" height="22">
                        <path
                            d="M16 14 L16 34 L32 34"
                            stroke="#fff"
                            stroke-width="4.5"
                            stroke-linecap="round"
                            stroke-linejoin="round"
                            fill="none"
                        />
                        <circle cx="32" cy="34" r="3.5" fill="#0F6E56" />
                    </svg>
                </span>
                <span class="brand-text">Лидерра<span class="dot">.</span></span>
            </a>

            <div class="error-content">
                <h1 class="err-code">
                    {{ config.code[0] }}<span class="accent">{{ config.code[1] }}</span
                    >{{ config.code[2] }}
                </h1>
                <h2 class="err-title">{{ config.title }}</h2>
                <p class="err-desc">{{ config.description }}</p>

                <div class="err-actions">
                    <v-btn
                        color="primary"
                        variant="flat"
                        :prepend-icon="config.primaryAction.icon"
                        :to="config.primaryAction.to"
                        @click="config.primaryAction.onClick?.()"
                    >
                        {{ config.primaryAction.label }}
                    </v-btn>
                    <v-btn
                        v-if="config.secondaryAction"
                        variant="outlined"
                        :prepend-icon="config.secondaryAction.icon"
                        :to="config.secondaryAction.to"
                        :href="config.secondaryAction.href"
                        @click="config.secondaryAction.onClick?.()"
                    >
                        {{ config.secondaryAction.label }}
                    </v-btn>
                </div>

                <div v-if="config.showStatusList" class="status-list">
                    <span v-for="s in statusList" :key="s.name" class="status-item">
                        <span class="dot" :style="{ background: statusColor(s.status) }" />
                        {{ s.name }} ·
                        {{ s.status === 'ok' ? 'OK' : s.status === 'degraded' ? 'деградация' : 'недоступен' }}
                    </span>
                </div>

                <div v-if="config.showRequestId" class="err-id">
                    <span class="text-caption text-medium-emphasis">{{ config.requestIdLabel }}</span>
                    <span class="request-id">{{ config.requestId }}</span>
                    <v-btn
                        icon="mdi-content-copy"
                        variant="text"
                        size="x-small"
                        :aria-label="`Скопировать ID ${config.requestIdLabel}`"
                        @click="copyRequestId"
                    />
                </div>

                <p v-if="errorCode === '404'" class="err-help text-caption">
                    Что-то не так? Напишите в
                    <a href="mailto:support@liderra.app" class="text-primary">support@liderra.app</a>
                </p>
            </div>
        </v-main>
    </v-app>
</template>

<style scoped>
.error-main {
    background: #012019;
    color: #fff;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.top-brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    color: #fff;
    text-decoration: none;
    padding: 24px 32px;
    font-weight: 600;
    font-size: 16px;
    letter-spacing: -0.01em;
}
.top-brand .mark {
    width: 24px;
    height: 24px;
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.06);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.top-brand .dot {
    color: #32c8a9;
}

.error-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 24px 32px 80px;
    text-align: center;
    max-width: 560px;
    margin: 0 auto;
}

.err-code {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 96px;
    font-weight: 600;
    line-height: 1;
    color: #fff;
    letter-spacing: -0.04em;
    margin: 0 0 16px;
}
.err-code .accent {
    color: #32c8a9;
}

.err-title {
    font-size: 28px;
    font-weight: 600;
    font-variation-settings: 'opsz' 28;
    letter-spacing: -0.018em;
    margin: 0 0 12px;
    color: #fff;
}

.err-desc {
    color: #b1c2bd;
    line-height: 1.55;
    font-size: 15px;
    margin: 0 0 24px;
}

.err-actions {
    display: flex;
    gap: 12px;
    margin-bottom: 24px;
    flex-wrap: wrap;
    justify-content: center;
}

.status-list {
    display: flex;
    gap: 16px;
    margin-bottom: 16px;
    flex-wrap: wrap;
    justify-content: center;
}
.status-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: #b1c2bd;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
}
.status-item .dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.err-id {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: rgba(255, 255, 255, 0.05);
    padding: 6px 10px;
    border-radius: 6px;
    margin-bottom: 12px;
}
.request-id {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 12px;
    color: #fff;
    font-weight: 500;
}

.err-help {
    color: #7a8c87;
    margin-top: 16px;
}
</style>
