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

vi.mock('../../resources/js/api/admin', () => ({
    impersonationActive: vi.fn(),
    impersonationRecent: vi.fn(),
    impersonationEnd: vi.fn(),
}));
vi.mock('../../resources/js/api/client', () => ({
    extractErrorMessage: vi.fn((_e, fb?: string) => fb ?? 'err'),
    apiClient: {},
    ensureCsrfCookie: vi.fn(),
}));

import * as adminApi from '../../resources/js/api/admin';
import AdminImpersonationView from '../../resources/js/views/admin/AdminImpersonationView.vue';

const mountView = async () => {
    const router = createRouter({
        history: createMemoryHistory(),
        routes: [{ path: '/admin/impersonation', component: AdminImpersonationView }],
    });
    await router.push('/admin/impersonation');
    await router.isReady();
    const wrapper = mount(AdminImpersonationView, {
        global: { plugins: [createVuetify(), router] },
    });
    await flushPromises();
    return wrapper;
};

describe('AdminImpersonationView.vue', () => {
    beforeEach(() => {
        vi.clearAllMocks();
        vi.mocked(adminApi.impersonationActive).mockResolvedValue([]);
        vi.mocked(adminApi.impersonationRecent).mockResolvedValue([]);
    });

    it('загружает active + recent на mount', async () => {
        await mountView();
        expect(adminApi.impersonationActive).toHaveBeenCalledTimes(1);
        expect(adminApi.impersonationRecent).toHaveBeenCalledTimes(1);
    });

    it('показывает empty-state когда обе secции пустые', async () => {
        const wrapper = await mountView();
        expect(wrapper.find('[data-testid="active-empty"]').exists()).toBe(true);
        expect(wrapper.find('[data-testid="recent-empty"]').exists()).toBe(true);
    });

    it('рендерит active-row для каждой активной сессии', async () => {
        vi.mocked(adminApi.impersonationActive).mockResolvedValue([
            {
                token_id: 42,
                tenant_id: 1,
                tenant_name: 'Окна Москва ООО',
                requested_by: 1,
                reason: 'Тикет SUP-12345 — клиент сообщил…',
                sent_to_email: 'admin@okna.ru',
                used_at: '2026-05-09T11:00:00',
                expires_at: '2026-05-09T11:15:00',
            },
        ]);
        const wrapper = await mountView();
        const rows = wrapper.findAll('[data-testid="active-row"]');
        expect(rows).toHaveLength(1);
        expect(rows[0].text()).toContain('Окна Москва ООО');
        expect(rows[0].text()).toContain('Тикет SUP-12345');
        expect(wrapper.find('[data-testid="end-btn-42"]').exists()).toBe(true);
    });

    it('click на «Завершить» вызывает API + перезагружает оба списка', async () => {
        vi.mocked(adminApi.impersonationActive).mockResolvedValue([
            {
                token_id: 42,
                tenant_id: 1,
                tenant_name: 'Окна Москва ООО',
                requested_by: 1,
                reason: 'reason ' + 'x'.repeat(30),
                sent_to_email: 'a@b.ru',
                used_at: '2026-05-09T11:00:00',
                expires_at: '2026-05-09T11:15:00',
            },
        ]);
        vi.mocked(adminApi.impersonationEnd).mockResolvedValue({
            token_id: 42,
            session_ended_at: '2026-05-09T11:30:00',
            message: 'OK',
        });
        const wrapper = await mountView();

        // Сбрасываем счётчики после initial mount-loadOnMount
        vi.mocked(adminApi.impersonationActive).mockClear();
        vi.mocked(adminApi.impersonationRecent).mockClear();

        await wrapper.find('[data-testid="end-btn-42"]').trigger('click');
        await flushPromises();

        expect(adminApi.impersonationEnd).toHaveBeenCalledWith(42);
        // Обе функции перезагружаются после end
        expect(adminApi.impersonationActive).toHaveBeenCalledTimes(1);
        expect(adminApi.impersonationRecent).toHaveBeenCalledTimes(1);
    });

    it('показывает error-alert если loadActive падает', async () => {
        vi.mocked(adminApi.impersonationActive).mockRejectedValueOnce(new Error('Network down'));
        const wrapper = await mountView();
        expect(wrapper.find('[data-testid="error-alert"]').exists()).toBe(true);
    });

    it('рендерит recent-row с длительностью', async () => {
        vi.mocked(adminApi.impersonationRecent).mockResolvedValue([
            {
                token_id: 100,
                tenant_id: 5,
                tenant_name: 'Двери Премиум',
                requested_by: 1,
                reason: 'historical reason ' + 'y'.repeat(30),
                used_at: '2026-05-08T10:00:00',
                session_ended_at: '2026-05-08T10:45:00',
                duration_seconds: 2700,
            },
        ]);
        const wrapper = await mountView();
        const rows = wrapper.findAll('[data-testid="recent-row"]');
        expect(rows).toHaveLength(1);
        expect(rows[0].text()).toContain('Двери Премиум');
        // 2700 сек = 45 мин 0 сек
        expect(rows[0].text()).toContain('45 мин');
    });
});
