import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mount, flushPromises } from '@vue/test-utils';
import { createVuetify } from 'vuetify';
import { createRouter, createMemoryHistory } from 'vue-router';
import AdminTenantDetailView from '../../resources/js/views/admin/AdminTenantDetailView.vue';
import type { AdminTenantDetailResponse } from '../../resources/js/api/admin';

vi.mock('../../resources/js/api/admin', async (importOriginal) => {
    const orig = await importOriginal<typeof import('../../resources/js/api/admin')>();
    return {
        ...orig,
        getAdminTenantDetail: vi.fn(),
    };
});

const adminApi = await import('../../resources/js/api/admin');

beforeEach(() => {
    vi.clearAllMocks();
});

function makeApiDetail(overrides: Partial<AdminTenantDetailResponse> = {}): AdminTenantDetailResponse {
    return {
        tenant: {
            id: 42,
            subdomain: 'okna-moscow',
            organization_name: 'Окна Москва ООО',
            contact_email: 'admin@okna-moscow.ru',
            status: 'active',
            balance_rub: '14250.00',
            balance_leads: 5,
            is_trial: false,
            last_activity_at: new Date(Date.now() - 30 * 60_000).toISOString(),
            tariff_id: 2,
            tariff_name: 'Команда',
            mrr_rub: '990.00',
            desired_daily_numbers: 12,
            chargeback_unrecovered_rub: '0.00',
            created_at: '2025-09-12T00:00:00+00:00',
        },
        users: [
            {
                id: 1,
                email: 'admin@okna-moscow.ru',
                first_name: 'Алексей',
                last_name: 'Петров',
                is_active: true,
                totp_enabled: true,
                last_active_at: new Date().toISOString(),
                last_login_at: new Date().toISOString(),
            },
            {
                id: 2,
                email: 'ivan@okna-moscow.ru',
                first_name: 'Иван',
                last_name: 'П.',
                is_active: true,
                totp_enabled: false,
                last_active_at: new Date().toISOString(),
                last_login_at: new Date().toISOString(),
            },
        ],
        projects: [
            {
                id: 1,
                name: 'Натяжные потолки',
                tag: 'natyazhnye-potolki',
                is_active: true,
                daily_limit_target: 8,
                suppliers_count: 3,
                leads_today: 6,
            },
        ],
        balance_history: [
            {
                id: 347,
                type: 'topup',
                amount_rub: '5000.00',
                amount_leads: 0,
                balance_rub_after: '14250.00',
                description: 'Пополнение ЮKassa',
                created_at: '2026-05-09T09:14:00+00:00',
            },
            {
                id: 346,
                type: 'lead_charge',
                amount_rub: '-1850.00',
                amount_leads: -1,
                balance_rub_after: '9250.00',
                description: 'Лид Анна Соколова',
                created_at: '2026-05-09T08:42:00+00:00',
            },
        ],
        activity: [
            {
                id: 1,
                event: 'webhook.received',
                deal_id: 4471,
                actor_email: null,
                context: null,
                created_at: '2026-05-09T08:42:00+00:00',
            },
            {
                id: 2,
                event: 'deal.status_changed',
                deal_id: 4470,
                actor_email: 'ivan@okna-moscow.ru',
                context: { from: 'viewed', to: 'in_progress' },
                created_at: '2026-05-09T07:18:00+00:00',
            },
        ],
        metrics: {
            leads_today: 11,
            leads_this_week: 42,
            leads_this_month: 187,
            avg_lead_cost_rub: 1980,
            runway_days: 50,
        },
        ...overrides,
    };
}

const buildRouter = (subdomain: string) => {
    const router = createRouter({
        history: createMemoryHistory(),
        routes: [
            { path: '/admin/tenants', name: 'admin-tenants', component: { template: '<div />' } },
            {
                path: '/admin/tenants/:code',
                name: 'admin-tenant-detail',
                component: AdminTenantDetailView,
            },
        ],
    });
    return router.push({ name: 'admin-tenant-detail', params: { code: subdomain } }).then(() => router);
};

const mountDetail = async (subdomain: string) => {
    const router = await buildRouter(subdomain);
    await router.isReady();
    const wrapper = mount(AdminTenantDetailView, {
        global: {
            plugins: [createVuetify(), router],
            stubs: { ImpersonationDialog: true },
        },
    });
    await flushPromises();
    return wrapper;
};

describe('AdminTenantDetailView.vue (API integration)', () => {
    it('вызывает getAdminTenantDetail с subdomain из route', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        await mountDetail('okna-moscow');
        expect(adminApi.getAdminTenantDetail).toHaveBeenCalledWith('okna-moscow');
    });

    it('рендерит карточку с organization_name + tariff_name', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        const wrapper = await mountDetail('okna-moscow');
        const text = wrapper.text();
        expect(text).toContain('Окна Москва ООО');
        expect(text).toContain('okna-moscow'); // code = subdomain
        expect(text).toContain('Команда');
    });

    it('показывает 4 KPI cards', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        const wrapper = await mountDetail('okna-moscow');
        ['kpi-balance', 'kpi-mrr', 'kpi-leads', 'kpi-avg-cost'].forEach((id) => {
            expect(wrapper.find(`[data-testid="${id}"]`).exists()).toBe(true);
        });
    });

    it('KPI Лиды показывает leads_today / desired_daily_numbers', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        const wrapper = await mountDetail('okna-moscow');
        const leadsCard = wrapper.find('[data-testid="kpi-leads"]');
        expect(leadsCard.text()).toContain('11 / 12');
    });

    it('по умолчанию активен таб «Финансы» с balance_history', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        const wrapper = await mountDetail('okna-moscow');
        expect(wrapper.find('[data-testid="pane-finance"]').exists()).toBe(true);
        expect(wrapper.text()).toContain('Пополнение ЮKassa');
    });

    it('переключение таба Пользователи показывает users', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        const wrapper = await mountDetail('okna-moscow');
        const vm = wrapper.vm as unknown as { activeTab: string };
        vm.activeTab = 'users';
        await wrapper.vm.$nextTick();
        expect(wrapper.find('[data-testid="pane-users"]').exists()).toBe(true);
        const text = wrapper.text();
        expect(text).toContain('admin@okna-moscow.ru');
        expect(text).toContain('Алексей Петров');
    });

    it('переключение таба Проекты показывает projects', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        const wrapper = await mountDetail('okna-moscow');
        const vm = wrapper.vm as unknown as { activeTab: string };
        vm.activeTab = 'projects';
        await wrapper.vm.$nextTick();
        expect(wrapper.find('[data-testid="pane-projects"]').exists()).toBe(true);
        const text = wrapper.text();
        expect(text).toContain('Натяжные потолки');
        expect(text).toContain('natyazhnye-potolki');
    });

    it('переключение таба Активность показывает event-коды + actor + summary', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        const wrapper = await mountDetail('okna-moscow');
        const vm = wrapper.vm as unknown as { activeTab: string };
        vm.activeTab = 'activity';
        await wrapper.vm.$nextTick();
        expect(wrapper.find('[data-testid="pane-activity"]').exists()).toBe(true);
        const text = wrapper.text();
        expect(text).toContain('webhook.received');
        expect(text).toContain('deal.status_changed');
        expect(text).toContain('ivan@okna-moscow.ru'); // actor_email
        expect(text).toContain('viewed → in_progress'); // summary из context
    });

    it('кнопка «Войти как клиент» open impersonationDialog', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(makeApiDetail());
        const wrapper = await mountDetail('okna-moscow');
        const vm = wrapper.vm as unknown as { impersonationOpen: boolean };
        const btn = wrapper.find('[data-testid="impersonate-btn"]');
        expect(btn.exists()).toBe(true);
        await btn.trigger('click');
        await wrapper.vm.$nextTick();
        expect(vm.impersonationOpen).toBe(true);
    });

    it('suspended-тенант имеет disabled impersonate-кнопку', async () => {
        const data = makeApiDetail({
            tenant: { ...makeApiDetail().tenant, status: 'suspended' },
        });
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(data);
        const wrapper = await mountDetail('okna-moscow');
        const btn = wrapper.find('[data-testid="impersonate-btn"]');
        expect(btn.exists()).toBe(true);
        expect(btn.attributes('disabled')).toBeDefined();
    });

    it('404 от API → fallback с tenant-not-found', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockRejectedValue({
            isAxiosError: true,
            response: { status: 404, data: { message: 'Тенант не найден.' } },
        });
        const wrapper = await mountDetail('unknown-tenant');
        expect(wrapper.find('[data-testid="tenant-not-found"]').exists()).toBe(true);
        expect(wrapper.text()).toContain('unknown-tenant');
        expect(wrapper.text()).toContain('не найден');
    });

    it('500 от API → fetch-error с кнопкой Повторить', async () => {
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockRejectedValue({
            isAxiosError: true,
            response: { status: 500, data: { message: 'Backend сломан' } },
        });
        const wrapper = await mountDetail('okna-moscow');
        expect(wrapper.find('[data-testid="tenant-fetch-error"]').exists()).toBe(true);
        expect(wrapper.text()).toContain('Backend сломан');
    });

    it('overdue (negative balance) — статус Просрочка', async () => {
        const data = makeApiDetail({
            tenant: {
                ...makeApiDetail().tenant,
                balance_rub: '-500.00',
                chargeback_unrecovered_rub: '500.00',
            },
        });
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(data);
        const wrapper = await mountDetail('okna-moscow');
        expect(wrapper.text()).toContain('Просрочка');
    });

    it('trial-тенант → tariff=Trial + mrr_rub скрыт (mrrRub null)', async () => {
        const data = makeApiDetail({
            tenant: {
                ...makeApiDetail().tenant,
                is_trial: true,
                mrr_rub: null,
            },
        });
        (adminApi.getAdminTenantDetail as ReturnType<typeof vi.fn>).mockResolvedValue(data);
        const wrapper = await mountDetail('okna-moscow');
        expect(wrapper.text()).toContain('Trial');
        expect(wrapper.text()).toContain('без оплаты');
    });
});
