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

import ChargesTab from '../../resources/js/views/billing/ChargesTab.vue';

vi.mock('axios');

// vite-plugin-vuetify auto-import регистрируется через vitest.config.ts,
// поэтому createVuetify() без явного передачи components работает.
const vuetify = createVuetify();

const mockData = {
    data: [
        {
            id: 1,
            charged_at: '2026-05-01T10:00:00Z',
            deal_id: 42,
            tier_no: 1,
            charge_source: 'rub',
            price_per_lead_kopecks: 50000,
        },
        {
            id: 2,
            charged_at: '2026-05-01T11:00:00Z',
            deal_id: 43,
            tier_no: 1,
            charge_source: 'prepaid',
            price_per_lead_kopecks: 0,
        },
    ],
    meta: { current_page: 1, last_page: 1, total: 2, per_page: 20 },
};

describe('ChargesTab', () => {
    beforeEach(() => {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        (axios.get as any).mockResolvedValue({ data: mockData });
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        (axios.post as any).mockResolvedValue({ data: new Blob() });
        globalThis.URL.createObjectURL = vi.fn(() => 'blob:url');
        globalThis.URL.revokeObjectURL = vi.fn();
    });

    it('renders 2 charge rows from API', async () => {
        const wrapper = mount(ChargesTab, {
            global: { plugins: [vuetify], stubs: { RouterLink: true } },
        });
        await new Promise((r) => setTimeout(r, 50));
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        expect((wrapper.vm as any).total).toBe(2);
    });

    it('period change triggers refetch', async () => {
        const wrapper = mount(ChargesTab, {
            global: { plugins: [vuetify], stubs: { RouterLink: true } },
        });
        await new Promise((r) => setTimeout(r, 50));
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        (wrapper.vm as any).period = 'last_month';
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        await (wrapper.vm as any).refresh();
        expect(axios.get).toHaveBeenLastCalledWith('/api/billing/charges', {
            params: expect.objectContaining({ period: 'last_month' }),
        });
    });

    it('does NOT render «Источник» filter dropdown', () => {
        const wrapper = mount(ChargesTab, {
            global: { plugins: [vuetify], stubs: { RouterLink: true } },
        });
        expect(wrapper.text()).not.toContain('Источник');
    });

    it('does NOT include charge_source in table headers', async () => {
        const wrapper = mount(ChargesTab, {
            global: { plugins: [vuetify], stubs: { RouterLink: true } },
        });
        await new Promise((r) => setTimeout(r, 50));
        const headers = wrapper.findAll('th').map((th) => th.text());
        expect(headers.some((h) => /Источник/.test(h))).toBe(false);
    });

    it('shows «из бесплатного» caption for historic prepaid rows (price_per_lead_kopecks=0)', async () => {
        const wrapper = mount(ChargesTab, {
            global: { plugins: [vuetify], stubs: { RouterLink: true } },
        });
        await new Promise((r) => setTimeout(r, 50));
        expect(wrapper.text()).toContain('из бесплатного');
    });

    it('exportCsv fires POST /export with blob response without charge_source param', async () => {
        const wrapper = mount(ChargesTab, {
            global: { plugins: [vuetify], stubs: { RouterLink: true } },
        });
        await new Promise((r) => setTimeout(r, 50));
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        await (wrapper.vm as any).exportCsv();
        expect(axios.post).toHaveBeenCalledWith(
            '/api/billing/charges/export',
            expect.objectContaining({ period: 'current_month' }),
            expect.objectContaining({ responseType: 'blob' }),
        );
        // charge_source must NOT be in params
        const callArgs = (axios.post as ReturnType<typeof vi.fn>).mock.calls[0][1] as Record<string, unknown>;
        expect(callArgs).not.toHaveProperty('charge_source');
    });
});
