import { test, expect } from '@playwright/test';

// Test 1: Song-Datenbank page renders with heading
test('song-datenbank page renders with correct heading', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Verify we're on songs page
    await expect(page).toHaveURL(/.*songs/);

    // Verify heading is visible
    await expect(page.getByRole('heading', { name: 'Song-Datenbank' })).toBeVisible();

    // Verify description text is visible
    await expect(page.getByText('Verwalte alle Songs, Übersetzungen und Arrangements.')).toBeVisible();
});

// Test 2: Song list shows table structure or empty state
test('song list shows table structure or empty state', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Check if songs exist or empty state is shown
    const songTable = page.locator('table');
    const emptyState = page.getByText(/Noch keine Songs vorhanden|Keine Songs gefunden/);

    const hasTable = await songTable.isVisible().catch(() => false);
    const isEmpty = await emptyState.isVisible().catch(() => false);

    // Either table exists OR empty state exists (but not both)
    expect(hasTable || isEmpty).toBe(true);
});

// Test 3: Song row shows structural elements (name, CCLI, dates)
test('song row shows name, CCLI ID, and date columns', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Check if songs exist
    const songTable = page.locator('table');
    const hasTable = await songTable.isVisible().catch(() => false);

    if (!hasTable) {
        // Skip test if no songs exist
        test.skip();
    }

    // Get first song row
    const firstRow = page.locator('tbody tr').first();
    await expect(firstRow).toBeVisible();

    // Verify row has cells for title, CCLI, created date, updated date, last used date
    const cells = firstRow.locator('td');
    const cellCount = await cells.count();

    // Should have at least 7 cells: title, CCLI, created, updated, last_used, translation, actions
    expect(cellCount).toBeGreaterThanOrEqual(7);

    // Verify title cell has text content
    const titleCell = cells.nth(0);
    const titleText = await titleCell.textContent();
    expect(titleText).toBeTruthy();
    expect(titleText?.length).toBeGreaterThan(0);

    // Verify CCLI cell exists (may be empty or have ID)
    const ccliCell = cells.nth(1);
    await expect(ccliCell).toBeVisible();
});

// Test 4: Search input filters songs
test('search input filters songs', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Check if songs exist
    const songTable = page.locator('table');
    const hasTable = await songTable.isVisible().catch(() => false);

    if (!hasTable) {
        // Skip test if no songs exist
        test.skip();
    }

    // Get initial song count
    const initialRows = page.locator('tbody tr');
    const initialCount = await initialRows.count();

    if (initialCount === 0) {
        test.skip();
    }

    // Type in search input
    const searchInput = page.getByTestId('song-list-search-input');
    await expect(searchInput).toBeVisible();

    // Type a search query that likely won't match anything
    await searchInput.fill('xyznonexistentquery123');

    // Wait for search to debounce and results to update
    await page.waitForTimeout(600);
    await page.waitForLoadState('networkidle');

    // Verify empty state or reduced results
    const emptyState = page.getByText('Keine Songs gefunden');
    const emptyStateVisible = await emptyState.isVisible().catch(() => false);

    // Either empty state is shown OR no rows exist
    const finalRows = page.locator('tbody tr');
    const finalCount = await finalRows.count();

    expect(emptyStateVisible || finalCount === 0).toBe(true);

    // Clear search
    await searchInput.fill('');
    await page.waitForTimeout(600);
    await page.waitForLoadState('networkidle');
});

// Test 5: Pagination works (if enough songs exist)
test('pagination controls work when multiple pages exist', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Check if pagination exists
    const paginationNav = page.locator('nav').filter({ has: page.getByTestId('song-list-pagination-prev') });
    const hasPagination = await paginationNav.isVisible().catch(() => false);

    if (!hasPagination) {
        // Skip test if pagination doesn't exist (not enough songs)
        test.skip();
    }

    // Verify prev/next buttons exist
    const prevButton = page.getByTestId('song-list-pagination-prev');
    const nextButton = page.getByTestId('song-list-pagination-next');

    await expect(prevButton).toBeVisible();
    await expect(nextButton).toBeVisible();

    // Verify page indicator text exists
    const pageIndicator = page.locator('p').filter({ hasText: /Seite \d+ von \d+/ });
    await expect(pageIndicator).toBeVisible();
});

// Test 6: Delete button triggers confirmation dialog (cancel → song still visible)
test('delete button triggers confirmation dialog and cancel keeps song', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Check if songs exist
    const songTable = page.locator('table');
    const hasTable = await songTable.isVisible().catch(() => false);

    if (!hasTable) {
        // Skip test if no songs exist
        test.skip();
    }

    // Get first song row
    const firstRow = page.locator('tbody tr').first();
    const hasDeleteButton = await firstRow.getByTestId('song-list-delete-button').isVisible().catch(() => false);

    if (!hasDeleteButton) {
        // Skip test if no delete button visible
        test.skip();
    }

    // Get song title before delete attempt
    const titleBefore = await firstRow.locator('td').first().textContent();

    // Click delete button
    const deleteButton = firstRow.getByTestId('song-list-delete-button');
    await deleteButton.click();

    // Wait for confirmation dialog to appear
    await page.waitForTimeout(200);

    // Verify confirmation dialog is visible
    const confirmDialog = page.locator('div').filter({ hasText: /Song löschen\?/ });
    const dialogVisible = await confirmDialog.isVisible().catch(() => false);

    if (!dialogVisible) {
        test.skip();
    }

    // Click cancel button
    const cancelButton = page.getByTestId('song-list-delete-cancel-button');
    await expect(cancelButton).toBeVisible();
    await cancelButton.click();

    // Wait for dialog to close
    await page.waitForTimeout(200);

    // Verify dialog is gone
    const dialogGone = await confirmDialog.isVisible().catch(() => false);
    expect(dialogGone).toBe(false);

    // Verify song is still visible in table
    const songStillVisible = await firstRow.isVisible().catch(() => false);
    expect(songStillVisible).toBe(true);

    // Verify title is unchanged
    const titleAfter = await firstRow.locator('td').first().textContent();
    expect(titleAfter).toBe(titleBefore);
});

// Test 7: Edit button opens SongEditModal
test('edit button opens song edit modal', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Check if songs exist
    const songTable = page.locator('table');
    const hasTable = await songTable.isVisible().catch(() => false);

    if (!hasTable) {
        // Skip test if no songs exist
        test.skip();
    }

    // Get first song row
    const firstRow = page.locator('tbody tr').first();
    const hasEditButton = await firstRow.getByTestId('song-list-edit-button').isVisible().catch(() => false);

    if (!hasEditButton) {
        // Skip test if no edit button visible
        test.skip();
    }

    // Click edit button
    const editButton = firstRow.getByTestId('song-list-edit-button');
    await editButton.click();

    // Wait for modal to appear
    await page.waitForTimeout(300);

    // Verify modal is visible (check for modal container with testid)
    const editModal = page.getByTestId('song-list-edit-modal');
    const modalVisible = await editModal.isVisible().catch(() => false);

    // Modal should be visible or at least the modal backdrop should appear
    expect(modalVisible).toBe(true);
});

// Test 8: Download button triggers download (assert non-error response)
test('download button triggers download action', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Check if songs exist
    const songTable = page.locator('table');
    const hasTable = await songTable.isVisible().catch(() => false);

    if (!hasTable) {
        // Skip test if no songs exist
        test.skip();
    }

    // Get first song row
    const firstRow = page.locator('tbody tr').first();
    const hasDownloadButton = await firstRow.getByTestId('song-list-download-button').isVisible().catch(() => false);

    if (!hasDownloadButton) {
        // Skip test if no download button visible
        test.skip();
    }

    // Listen for download event
    const downloadPromise = page.waitForEvent('download').catch(() => null);

    // Click download button
    const downloadButton = firstRow.getByTestId('song-list-download-button');
    await downloadButton.click();

    // Wait a bit for download to start or for any response
    await page.waitForTimeout(500);

    // Verify no error toast appeared
    const errorToast = page.locator('div').filter({ hasText: /Fehler|Error/ });
    const hasError = await errorToast.isVisible().catch(() => false);

    // Download may or may not trigger (depends on implementation)
    // But we verify no error occurred
    expect(hasError).toBe(false);
});

// Test 9: Translate button navigates to translate page
test('translate button navigates to translate page', async ({ page }) => {
    await page.goto('/songs');
    await page.waitForLoadState('networkidle');

    // Check if songs exist
    const songTable = page.locator('table');
    const hasTable = await songTable.isVisible().catch(() => false);

    if (!hasTable) {
        // Skip test if no songs exist
        test.skip();
    }

    // Get first song row
    const firstRow = page.locator('tbody tr').first();
    const hasTranslateLink = await firstRow.getByTestId('song-list-translate-link').isVisible().catch(() => false);

    if (!hasTranslateLink) {
        // Skip test if no translate link visible
        test.skip();
    }

    // Get the translate link href
    const translateLink = firstRow.getByTestId('song-list-translate-link');
    const href = await translateLink.getAttribute('href');

    // Verify href matches translate pattern
    expect(href).toMatch(/\/songs\/\d+\/translate/);

    // Click translate link
    await translateLink.click();

    // Wait for navigation
    await page.waitForLoadState('networkidle');

    // Verify we navigated to translate page
    await expect(page).toHaveURL(/\/songs\/\d+\/translate/);
});
