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

// Event lists are sorted by event date, not creation order, and this DB is shared
// (un-isolated) across spec files in the same test run, so the row we just created
// must be located by its unique date rather than by list position (.last()/.first()).
async function createEvent(page): Promise<string> {
    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 href = await row.locator('[data-testid^="btn-view-"]').getAttribute('href');
    return href ?? '';
}

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

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

        test('admin can view an event detail page', async ({ page }) => {
            await loginAs(page, ADMIN.mobile, ADMIN.password);
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);

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

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

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

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

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

    });

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

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

        test('new race form has race number field but no status field', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            await page.click('[data-testid="btn-new-race"]');

            const form = page.locator('[data-testid="race-form"]');
            await expect(form).toBeVisible();
            await expect(page.locator('[data-testid="input-race-number"]')).toBeVisible();
            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');
        });

        test('Races tab drops the bet-amount columns; the Report tab carries them with a totals row', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            await page.click('[data-testid="btn-new-race"]');
            await page.fill('[data-testid="input-race-number"]', '1');
            await page.click('[data-testid="btn-submit"]');

            const racesTable = page.locator('[data-testid="races-table"]');
            await expect(racesTable).toBeVisible();
            await expect(racesTable.locator('th', { hasText: 'Bet Amount' })).toHaveCount(0);
            await expect(racesTable.locator('th', { hasText: 'Revenue' })).toHaveCount(0);

            await page.click('[data-testid="tab-report"]');
            const reportTable = page.locator('[data-testid="report-table"]');
            await expect(reportTable).toBeVisible();
            await expect(reportTable.locator('th', { hasText: 'Bet Amount' })).toBeVisible();
            await expect(reportTable.locator('th', { hasText: 'Commission' })).toBeVisible();
            await expect(page.locator('[data-testid="report-combo-note"]')).toBeVisible();
            await expect(page.locator('[data-testid^="report-row-"]')).toHaveCount(1);
            await expect(page.locator('[data-testid="report-totals-row"]')).toBeVisible();
            await expect(page.locator('[data-testid="report-total-bet-amount"]')).toContainText('₱0.00');
            await expect(page.locator('[data-testid="report-total-commission"]')).toContainText('₱0.00');
            await expect(page.locator('[data-testid="report-total-revenue"]')).toContainText('₱0.00');
        });

        test('can create a race, which always starts as Open', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            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 expect(page).toHaveURL(`${BASE_URL}${eventUrl}`);
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();

            const row = page.locator('[data-testid^="race-row-"]').last();
            await expect(row).toContainText('Open');
            await expect(row).not.toContainText('Closed');
            await expect(row.locator('[data-testid^="btn-delete-race-"]')).toBeVisible();
        });

        test('view race page has a Close Betting button that closes betting after confirmation', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            await page.click('[data-testid="btn-new-race"]');
            await page.fill('[data-testid="input-race-number"]', '2');
            await page.click('[data-testid="btn-submit"]');

            const viewBtn = page.locator('[data-testid^="btn-view-race-"]').last();
            await viewBtn.click();

            await expect(page.locator('[data-testid="race-status"]')).toHaveText('Open');
            await expect(page.locator('[data-testid="btn-close-betting"]')).toBeVisible();
            await expect(page.locator('[data-testid="late-scratch-note"]')).toHaveText(
                'Late Scratch should be checked after the close betting.',
            );

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

            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
            await expect(page.locator('[data-testid="race-status"]')).toHaveText('Closed');
            await expect(page.locator('[data-testid="btn-close-betting"]')).toHaveCount(0);
            await expect(page.locator('[data-testid="late-scratch-note"]')).toHaveCount(0);
        });

        test('delete button disappears from the event page once a race is closed', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            await page.click('[data-testid="btn-new-race"]');
            await page.fill('[data-testid="input-race-number"]', '3');
            await page.click('[data-testid="btn-submit"]');

            const row = page.locator('[data-testid^="race-row-"]').last();
            const raceId = (await row.getAttribute('data-testid'))?.replace('race-row-', '');

            await page.click(`[data-testid="btn-view-race-${raceId}"]`);
            page.once('dialog', dialog => dialog.accept());
            await page.click('[data-testid="btn-close-betting"]');

            await page.goto(`${BASE_URL}${eventUrl}`);
            const closedRow = page.locator(`[data-testid="race-row-${raceId}"]`);
            await expect(closedRow).toContainText('Closed');
            await expect(closedRow.locator(`[data-testid="btn-delete-race-${raceId}"]`)).toHaveCount(0);
        });

        test('can delete an open race', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            await page.click('[data-testid="btn-new-race"]');
            await page.fill('[data-testid="input-race-number"]', '4');
            await page.click('[data-testid="btn-submit"]');

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

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

        test('deleting a race that still has a horse is blocked with a friendly error instead of crashing', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            await page.click('[data-testid="btn-new-race"]');
            await page.fill('[data-testid="input-race-number"]', '6');
            await page.click('[data-testid="btn-submit"]');

            const row = page.locator('[data-testid^="race-row-"]').last();
            const raceId = (await row.getAttribute('data-testid'))?.replace('race-row-', '');

            await page.click(`[data-testid="btn-view-race-${raceId}"]`);
            await page.click('[data-testid="btn-new-horse"]');
            await page.fill('[data-testid="input-horse-number"]', '1');
            await page.fill('[data-testid="input-horse-name"]', 'Guard Test Horse');
            await page.fill('[data-testid="input-horse-jockey"]', 'Guard Test Jockey');
            await page.click('[data-testid="btn-submit"]');

            await page.goto(`${BASE_URL}${eventUrl}`);
            page.once('dialog', dialog => dialog.accept());
            await page.click(`[data-testid="btn-delete-race-${raceId}"]`);

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

            await expect(page.locator(`[data-testid="race-row-${raceId}"]`)).toHaveCount(1);
        });

        test('race list shows the total number of horses enrolled in each race', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            await page.click('[data-testid="btn-new-race"]');
            await page.fill('[data-testid="input-race-number"]', '7');
            await page.click('[data-testid="btn-submit"]');

            const row = page.locator('[data-testid^="race-row-"]').last();
            const raceId = (await row.getAttribute('data-testid'))?.replace('race-row-', '');

            // No horses yet.
            await expect(page.locator(`[data-testid="race-horse-count-${raceId}"]`)).toHaveText('0');

            // Add a horse, then revisit the event to confirm the count updates.
            await page.click(`[data-testid="btn-view-race-${raceId}"]`);
            await page.click('[data-testid="btn-new-horse"]');
            await page.fill('[data-testid="input-horse-number"]', '1');
            await page.fill('[data-testid="input-horse-name"]', 'Horse One');
            await page.fill('[data-testid="input-horse-jockey"]', 'Jockey One');
            await page.click('[data-testid="btn-submit"]');

            await page.goto(`${BASE_URL}${eventUrl}`);
            await expect(page.locator(`[data-testid="race-horse-count-${raceId}"]`)).toHaveText('1');
        });

        test('race Delete button disappears once the event is published', async ({ page }) => {
            const eventUrl = await createEvent(page);
            await page.goto(`${BASE_URL}${eventUrl}`);
            await page.click('[data-testid="btn-new-race"]');
            await page.fill('[data-testid="input-race-number"]', '5');
            await page.click('[data-testid="btn-submit"]');

            const row = page.locator('[data-testid^="race-row-"]').last();
            const raceId = (await row.getAttribute('data-testid'))?.replace('race-row-', '');
            await expect(row.locator(`[data-testid="btn-delete-race-${raceId}"]`)).toBeVisible();

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

            const publishedRow = page.locator(`[data-testid="race-row-${raceId}"]`);
            await expect(publishedRow.locator(`[data-testid="btn-delete-race-${raceId}"]`)).toHaveCount(0);
        });

    });

});
