import { test, expect } from '@playwright/test';
import { BASE_URL, ADMIN, AGENT, USER, loginAs, uniqueFutureDate } from '../helpers';

test.describe('WFBO Event Management', () => {

    test.describe('access control', () => {

        test('admin can access events page', async ({ page }) => {
            await loginAs(page, ADMIN.mobile, ADMIN.password);
            await page.goto(`${BASE_URL}/wfbo/events`);

            await expect(page.locator('[data-testid="wfbo-sidebar"]')).toBeVisible();
        });

        test('regular user cannot access WFBO events', async ({ page }) => {
            await loginAs(page, USER.mobile, USER.password);
            await page.goto(`${BASE_URL}/wfbo/events`);

            await expect(page.locator('[data-testid="wfbo-sidebar"]')).not.toBeVisible();
        });

        test('agent cannot access WFBO events', async ({ page }) => {
            await loginAs(page, AGENT.mobile, AGENT.password);
            await page.goto(`${BASE_URL}/wfbo/events`);

            await expect(page.locator('[data-testid="wfbo-sidebar"]')).not.toBeVisible();
        });

        test('unauthenticated user is redirected away from events', async ({ page }) => {
            await page.context().clearCookies();
            await page.goto(`${BASE_URL}/wfbo/events`);

            expect(page.url()).not.toContain('/wfbo/events');
        });

    });

    test.describe('CRUD as admin', () => {

        test.beforeEach(async ({ page }) => {
            await loginAs(page, ADMIN.mobile, ADMIN.password);
        });

        test('events page loads with Add New button', async ({ page }) => {
            await page.goto(`${BASE_URL}/wfbo/events`);

            await expect(page.locator('[data-testid="wfbo-sidebar"]')).toBeVisible();
            await expect(page.locator('[data-testid="btn-new-event"]')).toBeVisible();
        });

        test('new event form loads with arena, date and video link fields but no status field', async ({ page }) => {
            await page.goto(`${BASE_URL}/wfbo/events/new`);

            const form = page.locator('[data-testid="event-form"]');
            await expect(form).toBeVisible();
            await expect(page.locator('[data-testid="select-event-management"]')).toBeVisible();
            await expect(page.locator('[data-testid="input-event-date"]')).toBeVisible();
            await expect(page.locator('[data-testid="input-event-video-url"]')).toBeVisible();
            await expect(page.locator('[data-testid="btn-submit"]')).toBeVisible();

            // Status must never be exposed in the create/edit form.
            await expect(form.locator('[data-testid*="status" i]')).toHaveCount(0);
            await expect(form.locator('[name*="status" i]')).toHaveCount(0);
            await expect(form).not.toContainText('Status');
            await expect(form).not.toContainText('Published');
        });

        test('can create a new event, which always starts as Draft', async ({ page }) => {
            const dateStr = uniqueFutureDate();
            await page.goto(`${BASE_URL}/wfbo/events/new`);
            await page.selectOption('[data-testid="select-event-management"]', { index: 1 });
            await page.fill('[data-testid="input-event-date"]', dateStr);
            await page.fill('[data-testid="input-event-video-url"]', 'https://example.com/stream');
            await page.click('[data-testid="btn-submit"]');

            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events`);
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
            await expect(page.locator('[data-testid="events-table"]')).toBeVisible();

            // Event lists are sorted by event date, not creation order, so find our
            // row by its unique date rather than assuming list position.
            const row = page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr });
            await expect(row).toContainText('Draft');
            await expect(row).not.toContainText('Published');
        });

        test('arena name still shows after reloading the list (cached read)', async ({ page }) => {
            const dateStr = uniqueFutureDate();
            await page.goto(`${BASE_URL}/wfbo/events/new`);
            const arenaName = await page.locator('[data-testid="select-event-management"] option').nth(1).textContent();
            await page.selectOption('[data-testid="select-event-management"]', { index: 1 });
            await page.fill('[data-testid="input-event-date"]', dateStr);
            await page.click('[data-testid="btn-submit"]');

            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events`);

            const row = page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr });
            await expect(row.locator('td').first()).toHaveText(arenaName ?? '');

            // The first render after save always hits a fresh DB query (cache was
            // just invalidated) - the regression only shows up once the list is
            // served from the cached read, i.e. on a subsequent load.
            await page.reload();
            const rowAfterReload = page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr });
            await expect(rowAfterReload.locator('td').first()).toHaveText(arenaName ?? '');
        });

        test('submitting without selecting an arena shows errors', async ({ page }) => {
            await page.goto(`${BASE_URL}/wfbo/events/new`);
            await page.fill('[data-testid="input-event-date"]', uniqueFutureDate());
            await page.click('[data-testid="btn-submit"]');

            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events/new`);
        });

        test('can edit an existing event', async ({ page }) => {
            const dateStr = uniqueFutureDate();
            await page.goto(`${BASE_URL}/wfbo/events/new`);
            await page.selectOption('[data-testid="select-event-management"]', { index: 1 });
            await page.fill('[data-testid="input-event-date"]', dateStr);
            await page.click('[data-testid="btn-submit"]');

            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events`);

            const row     = page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr });
            const editBtn = row.locator('[data-testid^="btn-edit-"]');

            await editBtn.click();
            await expect(page.locator('[data-testid="event-form"]')).toBeVisible();

            await page.fill('[data-testid="input-event-video-url"]', 'https://example.com/updated');
            await page.click('[data-testid="btn-submit"]');

            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events`);
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
        });

        test('can delete an event', async ({ page }) => {
            const dateStr = uniqueFutureDate();
            await page.goto(`${BASE_URL}/wfbo/events/new`);
            await page.selectOption('[data-testid="select-event-management"]', { index: 1 });
            await page.fill('[data-testid="input-event-date"]', dateStr);
            await page.click('[data-testid="btn-submit"]');

            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events`);

            const row       = page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr });
            const deleteBtn = row.locator('[data-testid^="btn-delete-"]');

            page.once('dialog', dialog => dialog.accept());
            await deleteBtn.click();

            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events`);
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
        });

        test('deleting an event that still has a race is blocked with a friendly error instead of crashing', async ({ page }) => {
            const dateStr = uniqueFutureDate();
            await page.goto(`${BASE_URL}/wfbo/events/new`);
            await page.selectOption('[data-testid="select-event-management"]', { index: 1 });
            await page.fill('[data-testid="input-event-date"]', dateStr);
            await page.click('[data-testid="btn-submit"]');
            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events`);

            const row       = page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr });
            const eventHref = await row.locator('[data-testid^="btn-view-"]').getAttribute('href');
            await page.goto(`${BASE_URL}${eventHref}`);
            await page.click('[data-testid="btn-new-race"]');
            await page.fill('[data-testid="input-race-number"]', '1');
            await page.click('[data-testid="btn-submit"]');

            await page.goto(`${BASE_URL}/wfbo/events`);
            const deleteBtn = page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr }).locator('[data-testid^="btn-delete-"]');
            page.once('dialog', dialog => dialog.accept());
            await deleteBtn.click();

            await expect(page.locator('[data-testid="flash-error"]')).toBeVisible();
            await expect(page.locator('[data-testid="flash-error"]')).toContainText('races');

            // The event itself was not deleted.
            await page.goto(`${BASE_URL}/wfbo/events`);
            await expect(page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr })).toHaveCount(1);
        });

        test('can publish an event from the view page', async ({ page }) => {
            const dateStr = uniqueFutureDate();
            await page.goto(`${BASE_URL}/wfbo/events/new`);
            await page.selectOption('[data-testid="select-event-management"]', { index: 1 });
            await page.fill('[data-testid="input-event-date"]', dateStr);
            await page.click('[data-testid="btn-submit"]');

            await expect(page).toHaveURL(`${BASE_URL}/wfbo/events`);
            const row       = page.locator('[data-testid^="event-row-"]').filter({ hasText: dateStr });
            const eventHref = await row.locator('[data-testid^="btn-view-"]').getAttribute('href');
            await page.goto(`${BASE_URL}${eventHref}`);

            await expect(page.locator('[data-testid="event-status"]')).toHaveText('Draft');
            await expect(page.locator('[data-testid="btn-publish-event"]')).toBeVisible();

            page.once('dialog', dialog => dialog.accept());
            await page.click('[data-testid="btn-publish-event"]');

            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
            await expect(page.locator('[data-testid="event-status"]')).toHaveText('Published');
            await expect(page.locator('[data-testid="btn-publish-event"]')).toHaveCount(0);
        });

        test('WFBO sidebar Live Racing group has Event Management link', async ({ page }) => {
            await page.goto(`${BASE_URL}/wfbo/events`);

            const link = page.locator('[data-testid="wfbo-nav-events"]');
            await expect(link).toBeVisible();
            await expect(link).toContainText('Event Management');
        });

    });

});
