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

test.describe('WFBO Karera Events', () => {

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

        test('operations user can access the events list', async ({ page }) => {
            await loginAs(page, OPERATIONS.mobile, OPERATIONS.password);
            await page.goto(`${BASE_URL}/wfbo/karera/events`);

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

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

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

        test('agent cannot access events', async ({ page }) => {
            await loginAs(page, AGENT.mobile, AGENT.password);
            await page.goto(`${BASE_URL}/wfbo/karera/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/karera/events`);

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

    });

    test.describe('event + race + entry flow as operations', () => {

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

        async function ensureArenaExists(page: import('@playwright/test').Page): Promise<string> {
            const arenaName = `Test Arena ${Date.now()}`;
            await page.goto(`${BASE_URL}/wfbo/karera/arenas/new`);
            await page.fill('[data-testid="input-name"]', arenaName);
            await page.click('[data-testid="btn-submit"]');
            await expect(page).toHaveURL(`${BASE_URL}/wfbo/karera/arenas`);
            return arenaName;
        }

        test('new event form loads', async ({ page }) => {
            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);

            await expect(page.locator('[data-testid="event-form"]')).toBeVisible();
            await expect(page.locator('[data-testid="input-event-date"]')).toBeVisible();
            await expect(page.locator('[data-testid="select-arena"]')).toBeVisible();
            await expect(page.locator('[data-testid="input-number-of-races"]')).toBeVisible();
        });

        test('submitting empty event form shows errors', async ({ page }) => {
            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.click('[data-testid="btn-submit"]');

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

        test('can create an event with multiple races, add entries with new names, and reuse an existing name', async ({ page }) => {
            const arenaName = await ensureArenaExists(page);

            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.fill('[data-testid="input-event-date"]', '2026-08-15');
            await page.selectOption('[data-testid="select-arena"]', { label: arenaName });
            await page.fill('[data-testid="input-number-of-races"]', '2');
            await page.click('[data-testid="btn-submit"]');

            await expect(page.url()).toMatch(/\/wfbo\/karera\/events\/\d+$/);
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
            await expect(page.locator('[data-testid="races-grid"]')).toBeVisible();
            await expect(page.locator('[data-testid^="race-card-"]')).toHaveCount(2);

            // Enter the first race and add an entry with brand-new horse/jockey/trainer names.
            const firstRaceCard = page.locator('[data-testid^="race-card-"]').first();
            await firstRaceCard.locator('[data-testid^="btn-actions-race-"]').click();
            await firstRaceCard.locator('[data-testid^="btn-view-race-"]').click();
            await page.click('[data-testid="btn-add-entry"]');
            await expect(page.locator('[data-testid="entry-form"]')).toBeVisible();

            const horseName   = `New Horse ${Date.now()}`;
            const jockeyName  = `New Jockey ${Date.now()}`;
            const trainerName = `New Trainer ${Date.now()}`;

            await page.fill('[data-testid="input-number"]', '4a');
            await select2Fill(page, 'input-horse-name', horseName);
            await select2Fill(page, 'input-jockey-name', jockeyName);
            await select2Fill(page, 'input-trainer-name', trainerName);
            await page.click('[data-testid="btn-submit"]');

            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
            await expect(page.locator('[data-testid="entries-table"]')).toBeVisible();

            // The new names should now exist as reference-data entities.
            await page.goto(`${BASE_URL}/wfbo/karera/horses`);
            await expect(page.locator(`[data-testid="horses-table"] >> text=${horseName}`)).toBeVisible();

            await page.goto(`${BASE_URL}/wfbo/karera/jockeys`);
            await expect(page.locator(`[data-testid="jockeys-table"] >> text=${jockeyName}`)).toBeVisible();

            await page.goto(`${BASE_URL}/wfbo/karera/trainers`);
            await expect(page.locator(`[data-testid="trainers-table"] >> text=${trainerName}`)).toBeVisible();
        });

        test('reusing an existing horse name does not create a duplicate', async ({ page }) => {
            const arenaName = await ensureArenaExists(page);
            const horseName = `Reused Horse ${Date.now()}`;

            // Seed a horse directly via the Horses screen.
            await page.goto(`${BASE_URL}/wfbo/karera/horses/new`);
            await page.fill('[data-testid="input-name"]', horseName);
            await page.click('[data-testid="btn-submit"]');
            await expect(page).toHaveURL(`${BASE_URL}/wfbo/karera/horses`);

            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.fill('[data-testid="input-event-date"]', '2026-08-16');
            await page.selectOption('[data-testid="select-arena"]', { label: arenaName });
            await page.fill('[data-testid="input-number-of-races"]', '1');
            await page.click('[data-testid="btn-submit"]');

            await page.locator('[data-testid^="btn-actions-race-"]').first().click();
            await page.locator('[data-testid^="btn-view-race-"]').first().click();
            await page.click('[data-testid="btn-add-entry"]');
            await expect(page.locator('[data-testid="entry-form"]')).toBeVisible();
            await page.fill('[data-testid="input-number"]', '1');
            await select2Fill(page, 'input-horse-name', horseName);
            await select2Fill(page, 'input-jockey-name', `Jockey ${Date.now()}`);
            await select2Fill(page, 'input-trainer-name', `Trainer ${Date.now()}`);
            await page.click('[data-testid="btn-submit"]');

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

            await page.goto(`${BASE_URL}/wfbo/karera/horses`);
            await expect(page.locator(`[data-testid="horses-table"] >> text=${horseName}`)).toHaveCount(1);
        });

        test('add entry modal reopens automatically when submission has errors', async ({ page }) => {
            const arenaName = await ensureArenaExists(page);

            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.fill('[data-testid="input-event-date"]', '2026-08-20');
            await page.selectOption('[data-testid="select-arena"]', { label: arenaName });
            await page.fill('[data-testid="input-number-of-races"]', '1');
            await page.click('[data-testid="btn-submit"]');

            await page.locator('[data-testid^="btn-actions-race-"]').first().click();
            await page.locator('[data-testid^="btn-view-race-"]').first().click();
            await expect(page.locator('[data-testid="entry-form"]')).not.toBeVisible();

            await page.click('[data-testid="btn-add-entry"]');
            await expect(page.locator('[data-testid="entry-form"]')).toBeVisible();
            await page.click('[data-testid="btn-submit"]');

            await expect(page.locator('[data-testid="flash-error"]').first()).toBeVisible();
            await expect(page.locator('[data-testid="entry-form"]')).toBeVisible();
        });

        test('can edit and delete an entry', async ({ page }) => {
            const arenaName = await ensureArenaExists(page);

            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.fill('[data-testid="input-event-date"]', '2026-08-17');
            await page.selectOption('[data-testid="select-arena"]', { label: arenaName });
            await page.fill('[data-testid="input-number-of-races"]', '1');
            await page.click('[data-testid="btn-submit"]');

            await page.locator('[data-testid^="btn-actions-race-"]').first().click();
            await page.locator('[data-testid^="btn-view-race-"]').first().click();
            await page.click('[data-testid="btn-add-entry"]');
            await expect(page.locator('[data-testid="entry-form"]')).toBeVisible();
            await page.fill('[data-testid="input-number"]', '1');
            await select2Fill(page, 'input-horse-name', `Edit Horse ${Date.now()}`);
            await select2Fill(page, 'input-jockey-name', `Edit Jockey ${Date.now()}`);
            await select2Fill(page, 'input-trainer-name', `Edit Trainer ${Date.now()}`);
            await page.click('[data-testid="btn-submit"]');

            const editBtn = page.locator('[data-testid^="btn-edit-"]').last();
            await editBtn.click();
            await expect(page.locator('[data-testid="entry-form"]')).toBeVisible();
            await page.fill('[data-testid="input-number"]', '1b');
            await page.click('[data-testid="btn-submit"]');
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();

            const deleteBtn = page.locator('[data-testid^="btn-delete-"]').last();
            page.once('dialog', dialog => dialog.accept());
            await deleteBtn.click();
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
        });

        test('cannot reduce number of races below existing count', async ({ page }) => {
            const arenaName = await ensureArenaExists(page);

            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.fill('[data-testid="input-event-date"]', '2026-08-18');
            await page.selectOption('[data-testid="select-arena"]', { label: arenaName });
            await page.fill('[data-testid="input-number-of-races"]', '3');
            await page.click('[data-testid="btn-submit"]');

            const url = page.url();
            await page.goto(`${url}/edit`);
            await page.fill('[data-testid="input-number-of-races"]', '1');
            await page.click('[data-testid="btn-submit"]');

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

        test('can delete a race and delete an event', async ({ page }) => {
            const arenaName = await ensureArenaExists(page);

            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.fill('[data-testid="input-event-date"]', '2026-08-19');
            await page.selectOption('[data-testid="select-arena"]', { label: arenaName });
            await page.fill('[data-testid="input-number-of-races"]', '2');
            await page.click('[data-testid="btn-submit"]');

            await page.locator('[data-testid^="btn-actions-race-"]').first().click();
            const deleteRaceBtn = page.locator('[data-testid^="btn-delete-race-"]').first();
            page.once('dialog', dialog => dialog.accept());
            await deleteRaceBtn.click();
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
            await expect(page.locator('[data-testid^="race-card-"]')).toHaveCount(1);

            await page.goto(`${BASE_URL}/wfbo/karera/events`);
            const deleteEventBtn = page.locator('[data-testid^="btn-delete-"]').last();
            page.once('dialog', dialog => dialog.accept());
            await deleteEventBtn.click();
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
        });

        test('can add a race manually and race cards show entry count and betting status', async ({ page }) => {
            const arenaName = await ensureArenaExists(page);

            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.fill('[data-testid="input-event-date"]', '2026-08-21');
            await page.selectOption('[data-testid="select-arena"]', { label: arenaName });
            await page.fill('[data-testid="input-number-of-races"]', '1');
            await page.click('[data-testid="btn-submit"]');

            const eventUrl = page.url();
            await expect(page.locator('[data-testid^="race-card-"]')).toHaveCount(1);

            const raceCard = page.locator('[data-testid^="race-card-"]').first();
            await expect(raceCard.locator('[data-testid^="entry-count-"]')).toHaveText('0 entries');
            await expect(raceCard.locator('[data-testid^="betting-status-"]')).toHaveValue('open');

            await page.click('[data-testid="btn-add-race"]');
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
            await expect(page.locator('[data-testid^="race-card-"]')).toHaveCount(2);
            await expect(page.locator('[data-testid="event-arena"]')).toContainText('2 race(s)');

            // Add an entry to the first race and confirm the card's entry count updates.
            await raceCard.locator('[data-testid^="btn-actions-race-"]').click();
            await raceCard.locator('[data-testid^="btn-view-race-"]').click();
            await page.click('[data-testid="btn-add-entry"]');
            await page.fill('[data-testid="input-number"]', '1');
            await select2Fill(page, 'input-horse-name', `Card Horse ${Date.now()}`);
            await select2Fill(page, 'input-jockey-name', `Card Jockey ${Date.now()}`);
            await select2Fill(page, 'input-trainer-name', `Card Trainer ${Date.now()}`);
            await page.click('[data-testid="btn-submit"]');

            await page.goto(eventUrl);
            await expect(page.locator('[data-testid^="entry-count-"]').first()).toHaveText('1 entry');
        });

        test('can toggle a race betting status directly from the event page', async ({ page }) => {
            const arenaName = await ensureArenaExists(page);

            await page.goto(`${BASE_URL}/wfbo/karera/events/new`);
            await page.fill('[data-testid="input-event-date"]', '2026-08-22');
            await page.selectOption('[data-testid="select-arena"]', { label: arenaName });
            await page.fill('[data-testid="input-number-of-races"]', '1');
            await page.click('[data-testid="btn-submit"]');

            const raceCard = page.locator('[data-testid^="race-card-"]').first();
            const statusSelect = raceCard.locator('[data-testid^="betting-status-"]');
            await expect(statusSelect).toHaveValue('open');

            page.once('dialog', dialog => dialog.accept());
            await statusSelect.selectOption('closed');
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
            await expect(page.locator('[data-testid^="betting-status-"]').first()).toHaveText('Closed');

            await page.goto(page.url());
            await expect(page.locator('[data-testid^="betting-status-"]').first()).toHaveText('Closed');
        });

    });

});
