import { describe, it, expect, vi, afterEach } from 'vitest';
import { render, screen, cleanup } from '@testing-library/svelte';
import { tick } from 'svelte';
import AddToCollectionModal from './AddToCollectionModal.svelte';

// Stub the API modules at the import-graph level so the modal exercises
// its dispatch (manga vs page) without hitting fetch.
const collectionsApi = vi.hoisted(() => ({
    listMyCollections: vi.fn(),
    getMyCollectionsContaining: vi.fn(),
    addMangaToCollection: vi.fn(),
    removeMangaFromCollection: vi.fn(),
    createCollection: vi.fn()
}));
const pageCollectionsApi = vi.hoisted(() => ({
    getMyCollectionsContainingPage: vi.fn(),
    addPageToCollection: vi.fn(),
    removePageFromCollection: vi.fn()
}));

vi.mock('$lib/api/collections', () => collectionsApi);
vi.mock('$lib/api/page_collections', () => pageCollectionsApi);

afterEach(() => {
    cleanup();
    vi.clearAllMocks();
});

function summary(id: string, name: string, containing: string[] = []) {
    return {
        id,
        user_id: 'u1',
        name,
        description: null,
        created_at: '2026-01-01T00:00:00Z',
        updated_at: '2026-01-01T00:00:00Z',
        manga_count: 0,
        sample_covers: [],
        _containing: containing
    };
}

describe('AddToCollectionModal', () => {
    it('manga target loads via getMyCollectionsContaining', async () => {
        collectionsApi.listMyCollections.mockResolvedValueOnce({
            items: [summary('c1', 'Favorites')],
            page: { limit: 200, offset: 0, total: 1 }
        });
        collectionsApi.getMyCollectionsContaining.mockResolvedValueOnce(['c1']);

        render(AddToCollectionModal, {
            props: {
                open: true,
                target: { kind: 'manga', id: 'm1' },
                onClose: () => {}
            }
        });
        // Wait for the $effect → load() → await chain to settle.
        await tick();
        await Promise.resolve();
        await tick();

        expect(collectionsApi.getMyCollectionsContaining).toHaveBeenCalledWith('m1');
        expect(pageCollectionsApi.getMyCollectionsContainingPage).not.toHaveBeenCalled();
    });

    it('page target loads via getMyCollectionsContainingPage', async () => {
        collectionsApi.listMyCollections.mockResolvedValueOnce({
            items: [summary('c1', 'Favorite panels')],
            page: { limit: 200, offset: 0, total: 1 }
        });
        pageCollectionsApi.getMyCollectionsContainingPage.mockResolvedValueOnce([]);

        render(AddToCollectionModal, {
            props: {
                open: true,
                target: { kind: 'page', id: 'p1' },
                onClose: () => {}
            }
        });
        await tick();
        await Promise.resolve();
        await tick();

        expect(pageCollectionsApi.getMyCollectionsContainingPage).toHaveBeenCalledWith('p1');
        expect(collectionsApi.getMyCollectionsContaining).not.toHaveBeenCalled();
        expect(screen.getByText('Favorite panels')).toBeTruthy();
    });

    it('does not load when closed', () => {
        render(AddToCollectionModal, {
            props: {
                open: false,
                target: { kind: 'manga', id: 'm1' },
                onClose: () => {}
            }
        });
        expect(collectionsApi.listMyCollections).not.toHaveBeenCalled();
    });
});
