import { describe, it, expect, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import { createPinia, setActivePinia } from 'pinia';
import { createVuetify } from 'vuetify';
import { createRouter, createMemoryHistory } from 'vue-router';

// Мокаем api/notifications до import'а AppLayout (использует store, который импортит api).
vi.mock('../../resources/js/api/notifications', () => ({
    listNotifications: vi.fn().mockResolvedValue({ items: [], unread_count: 0, total: 0 }),
    markNotificationRead: vi.fn(),
    markAllNotificationsRead: vi.fn(),
    deleteNotification: vi.fn(),
}));

import * as notificationsApi from '../../resources/js/api/notifications';
import AppLayout from '../../resources/js/layouts/AppLayout.vue';
import { useAuthStore } from '../../resources/js/stores/auth';
import { useNotificationsStore } from '../../resources/js/stores/notifications';
import { useDealsCountStore } from '../../resources/js/stores/dealsCount';
import type { AuthUser } from '../../resources/js/api/auth';

const mockUser: AuthUser = {
    id: 1,
    email: 'ivan.petrov@example.ru',
    first_name: 'Иван',
    last_name: 'Петров',
    tenant_id: 1,
    totp_enabled: false,
    last_login_at: null,
};

// AppLayout содержит sidebar (6 nav-items в 3 группах) + topbar (crumb/search/user) + RouterView.

const mountAppLayout = async (path = '/dashboard', user: AuthUser | null = mockUser) => {
    setActivePinia(createPinia());
    const auth = useAuthStore();
    auth.user = user;
    // B2: init deals count so badge renders (replaces hardcoded 247 in AppSidebar).
    useDealsCountStore().count = 247;

    const router = createRouter({
        history: createMemoryHistory(),
        routes: [
            { path: '/dashboard', component: { template: '<div>dashboard</div>' } },
            { path: '/deals', component: { template: '<div>deals</div>' } },
            { path: '/kanban', component: { template: '<div>kanban</div>' } },
            { path: '/projects', component: { template: '<div>projects</div>' } },
            { path: '/billing', component: { template: '<div>billing</div>' } },
            { path: '/reports', component: { template: '<div>reports</div>' } },
            { path: '/settings', component: { template: '<div>settings</div>' } },
            // Не в sidebar nav, но имеют meta.title — topbar должен брать title оттуда.
            { path: '/import', component: { template: '<div>import</div>' }, meta: { title: 'Импорт данных' } },
        ],
    });
    await router.push(path);
    await router.isReady();
    return mount(AppLayout, {
        global: { plugins: [createVuetify(), router] },
    });
};

describe('AppLayout.vue', () => {
    it('монтируется без ошибок', async () => {
        const wrapper = await mountAppLayout();
        expect(wrapper.exists()).toBe(true);
    });

    it('содержит брендовый блок «Лидерра.» в sidebar', async () => {
        const wrapper = await mountAppLayout();
        expect(wrapper.text()).toContain('Лидерра');
    });

    it('содержит 3 nav-группы: Работа, Финансы, Команда', async () => {
        const wrapper = await mountAppLayout();
        const text = wrapper.text();
        expect(text).toContain('Работа');
        expect(text).toContain('Финансы');
        expect(text).toContain('Команда');
    });

    it('содержит 6 nav-пунктов (Импорт данных + Отчёты убраны по требованию заказчика)', async () => {
        const wrapper = await mountAppLayout();
        const text = wrapper.text();
        ['Проекты', 'Сделки', 'Канбан', 'Дашборд', 'Биллинг', 'Настройки'].forEach((label) =>
            expect(text).toContain(label),
        );
        expect(text).not.toContain('Менеджеры');
        expect(text).not.toContain('Напоминания');
        expect(text).not.toContain('Импорт данных');
        expect(text).not.toContain('Отчёты');
    });

    it('показывает счётчики только у пунктов с count', async () => {
        const wrapper = await mountAppLayout();
        const text = wrapper.text();
        expect(text).toContain('247'); // Сделки (mock)
    });

    it('breadcrumb показывает текущую страницу', async () => {
        const wrapper = await mountAppLayout('/dashboard');
        expect(wrapper.text()).toContain('Дашборд');
    });

    it('topbar title для /import берётся из route.meta.title (Импорт данных)', async () => {
        const wrapper = await mountAppLayout('/import');
        expect(wrapper.text()).toContain('Импорт данных');
    });

    it('user-chip показывает initials и shortName из store user', async () => {
        const wrapper = await mountAppLayout();
        const text = wrapper.text();
        expect(text).toContain('ИП'); // initials Иван Петров
        expect(text).toContain('Иван П.'); // shortName
    });

    it('при null user (гость) показывает «?» и «Гость»', async () => {
        const wrapper = await mountAppLayout('/dashboard', null);
        const text = wrapper.text();
        expect(text).toContain('Гость');
        expect(text).toContain('?');
    });

    it('при отсутствии first_name fallback на email', async () => {
        const wrapper = await mountAppLayout('/dashboard', {
            ...mockUser,
            first_name: null,
            last_name: null,
        });
        expect(wrapper.text()).toContain('ivan.petrov@example.ru');
    });

    it('bell-icon кнопка существует', async () => {
        const wrapper = await mountAppLayout();
        const bellBtn = wrapper.find('[data-testid="notifications-btn"]');
        expect(bellBtn.exists()).toBe(true);
    });

    it('pip скрыт когда unreadCount=0 (default state)', async () => {
        const wrapper = await mountAppLayout();
        await wrapper.vm.$nextTick();
        const pip = wrapper.find('[data-testid="notifications-pip"]');
        expect(pip.exists()).toBe(false);
    });

    it('pip показывает unreadCount когда > 0', async () => {
        const wrapper = await mountAppLayout();
        const store = useNotificationsStore();
        store.unreadCount = 5;
        await wrapper.vm.$nextTick();

        const pip = wrapper.find('[data-testid="notifications-pip"]');
        expect(pip.exists()).toBe(true);
        expect(pip.text()).toBe('5');
    });

    it('pip показывает «99+» когда unreadCount > 99', async () => {
        const wrapper = await mountAppLayout();
        const store = useNotificationsStore();
        store.unreadCount = 142;
        await wrapper.vm.$nextTick();

        const pip = wrapper.find('[data-testid="notifications-pip"]');
        expect(pip.text()).toBe('99+');
    });

    it('listNotifications вызывается на mount при наличии user', async () => {
        await mountAppLayout('/dashboard', mockUser);
        expect(notificationsApi.listNotifications).toHaveBeenCalled();
    });

    it('listNotifications НЕ вызывается на mount без user', async () => {
        vi.mocked(notificationsApi.listNotifications).mockClear();
        await mountAppLayout('/dashboard', null);
        expect(notificationsApi.listNotifications).not.toHaveBeenCalled();
    });
});
