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

// Setup helpers mirror tests/acceptance_test/front/live_racing.spec.ts.

async function createArena(page: Page, betTypeKey: string, amount: string): Promise<string> {
    const name = `Bets Arena ${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
    const fieldTestId = 'input-' + betTypeKey.replace(/_/g, '-') + '-amount';

    await page.goto(`${BASE_URL}/wfbo/managements/new`);
    await page.fill('[data-testid="input-name"]', name);
    await page.fill(`[data-testid="${fieldTestId}"]`, amount);
    await page.click('[data-testid="btn-submit"]');
    await expect(page).toHaveURL(`${BASE_URL}/wfbo/managements`);

    return name;
}

async function createEventShowUrl(page: Page, arenaName: string): Promise<string> {
    const dateStr = uniqueFutureDate();
    await page.goto(`${BASE_URL}/wfbo/events/new`);
    await page.selectOption('[data-testid="select-event-management"]', { label: arenaName });
    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');
    return eventHref ?? '';
}

async function addRace(page: Page, eventUrl: string, raceNumber: number): Promise<string> {
    await page.goto(`${BASE_URL}${eventUrl}`);
    await page.click('[data-testid="btn-new-race"]');
    await page.fill('[data-testid="input-race-number"]', String(raceNumber));
    await page.click('[data-testid="btn-submit"]');

    const row = page.locator('[data-testid^="race-row-"]').filter({ hasText: String(raceNumber) });
    const raceHref = await row.locator('[data-testid^="btn-view-race-"]').getAttribute('href');
    return raceHref ?? '';
}

async function addHorse(page: Page, raceUrl: string, horseNumber: number): Promise<string> {
    await page.goto(`${BASE_URL}${raceUrl}`);
    await page.click('[data-testid="btn-new-horse"]');
    await page.fill('[data-testid="input-horse-number"]', String(horseNumber));
    await page.fill('[data-testid="input-horse-name"]', `Horse ${horseNumber}`);
    await page.fill('[data-testid="input-horse-jockey"]', `Jockey ${horseNumber}`);
    await page.click('[data-testid="btn-submit"]');

    const row = page.locator('[data-testid^="horse-row-"]').last();
    const horseId = (await row.getAttribute('data-testid'))?.replace('horse-row-', '');
    return horseId ?? '';
}

async function offerSingleBetType(page: Page, eventUrl: string, key: string, raceId: string): Promise<void> {
    await page.goto(`${BASE_URL}${eventUrl}?tab=bet-types`);
    await page.check(`[data-testid="checkbox-leg-${key}-${raceId}"]`);
    await page.click('[data-testid="btn-save-bet-types"]');
    await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
}

async function publishEvent(page: Page, eventUrl: string): Promise<void> {
    await page.goto(`${BASE_URL}${eventUrl}`);
    page.once('dialog', dialog => dialog.accept());
    await page.click('[data-testid="btn-publish-event"]');
}

/**
 * Full setup: arena + published event with one open race and 2 horses, Win
 * offered, Live Racing enabled, and one straight Win bet placed as USER.
 * Leaves the browser logged in as ADMIN. Returns the placed bet's reference
 * number, found via the player's own history page (its testid embeds no
 * reference, so this reads the visible text directly).
 */
async function placeAWinBet(page: Page, arenaAmount = '10.00'): Promise<{ arenaName: string; eventUrl: string; eventId: string; raceId: string; reference: string }> {
    await loginAs(page, ADMIN.mobile, ADMIN.password);

    const arenaName = await createArena(page, 'win', arenaAmount);
    const eventUrl  = await createEventShowUrl(page, arenaName);
    const eventId   = eventUrl.split('/').pop() ?? '';
    const raceUrl   = await addRace(page, eventUrl, Date.now() % 1000);
    const raceId    = raceUrl.split('/').pop() ?? '';
    const horse1    = await addHorse(page, raceUrl, 1);
    await addHorse(page, raceUrl, 2);

    await offerSingleBetType(page, eventUrl, 'win', raceId);
    await publishEvent(page, eventUrl);
    await ensureLiveRacingEnabled(page);

    await loginAs(page, USER.mobile, USER.password);
    await placeWizardBet(page, { eventId, raceId, cardLabel: /^Win$/, positions: { 1: [horse1] } });

    await page.goto(`${BASE_URL}/play/live-racing/history`);
    const row = page.locator(`[data-testid^="live-racing-history-row-"][data-arena="${arenaName}"]`);
    await expect(row).toBeVisible();
    const reference = ((await row.textContent()) ?? '').match(/Ref:\s*(\S+)/)?.[1] ?? '';

    await loginAs(page, ADMIN.mobile, ADMIN.password);

    return { arenaName, eventUrl, eventId, raceId, reference };
}

test.describe('WFBO Live Racing Bets', () => {

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

        test('admin can view the live racing bets page', async ({ page }) => {
            await loginAs(page, ADMIN.mobile, ADMIN.password);
            await page.goto(`${BASE_URL}/wfbo/live-racing/bets`);

            await expect(page.locator('[data-testid="wfbo-sidebar"]')).toBeVisible();
            await expect(page.locator('[data-testid="live-racing-bets-table"], [data-testid="empty-state"]')).toBeVisible();
        });

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

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

        test('agent cannot access the live racing bets page', async ({ page }) => {
            await loginAs(page, AGENT.mobile, AGENT.password);
            await page.goto(`${BASE_URL}/wfbo/live-racing/bets`);

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

    });

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

        test('a placed bet appears in the list with the correct columns', async ({ page }) => {
            const { reference } = await placeAWinBet(page);

            await page.goto(`${BASE_URL}/wfbo/live-racing/bets?period=this_month`);
            const row = page.locator('[data-testid^="live-racing-bet-row-"]').filter({ hasText: reference });

            await expect(row).toContainText('Win');
            await expect(row).toContainText('₱10.00');
            await expect(row).toContainText('Pending');
        });

        test('filtering by status narrows the list to matching bets only', async ({ page }) => {
            const { reference } = await placeAWinBet(page);

            await page.goto(`${BASE_URL}/wfbo/live-racing/bets?period=this_month&status=pending`);
            await expect(page.locator('[data-testid^="live-racing-bet-row-"]').filter({ hasText: reference })).toHaveCount(1);

            await page.goto(`${BASE_URL}/wfbo/live-racing/bets?period=this_month&status=won`);
            await expect(page.locator('[data-testid^="live-racing-bet-row-"]').filter({ hasText: reference })).toHaveCount(0);
        });

        test('filtering by reference number finds the exact bet', async ({ page }) => {
            const { reference } = await placeAWinBet(page);

            await page.goto(`${BASE_URL}/wfbo/live-racing/bets?period=this_month&reference=${encodeURIComponent(reference)}`);
            await expect(page.locator('[data-testid^="live-racing-bet-row-"]')).toHaveCount(1);
            await expect(page.locator('[data-testid^="live-racing-bet-row-"]').first()).toContainText(reference);
        });

        test('filtering by event narrows the list to that event only', async ({ page }) => {
            const first  = await placeAWinBet(page);
            const second = await placeAWinBet(page);

            await page.goto(`${BASE_URL}/wfbo/live-racing/bets?period=this_month&event_id=${first.eventId}`);
            await expect(page.locator('[data-testid^="live-racing-bet-row-"]').filter({ hasText: first.reference })).toHaveCount(1);
            await expect(page.locator('[data-testid^="live-racing-bet-row-"]').filter({ hasText: second.reference })).toHaveCount(0);
        });

        test('the stats row reflects the filtered bets', async ({ page }) => {
            const { eventId } = await placeAWinBet(page);

            await page.goto(`${BASE_URL}/wfbo/live-racing/bets?period=this_month&event_id=${eventId}`);
            await expect(page.locator('[data-testid="stat-total"]')).toHaveText('1');
            await expect(page.locator('[data-testid="stat-pending"]')).toHaveText('1');
        });

    });

});
