import { test, expect, type Page } from '@playwright/test';
import { BASE_URL, ADMIN, AUDITOR, loginAs, registerAndLogin, adjustWalletAsAuditor } from '../helpers';

// WFBO ▸ Games ▸ Leaderboard ranks players over the mini-game bets, filtered
// by game and date range. A fresh player drops two ₱10 Pachinko balls; the
// outcome is random, so the checks use the stakes (Total Bet) and the
// payouts the bet endpoint returned.

async function ensurePachinkoEnabled(page: Page): Promise<void> {
    await loginAs(page, ADMIN.mobile, ADMIN.password);
    await page.goto(`${BASE_URL}/wfbo/pachinko/settings`, { waitUntil: 'domcontentloaded' });
    const toggle = page.locator('[data-testid="toggle-pk-enabled"]');
    if (!(await toggle.isChecked())) {
        await toggle.check();
        await page.click('[data-testid="btn-save-pk-settings"]');
        await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
    }
}

/** Drops one Pachinko ball as the logged-in player; returns the payout. */
async function dropPachinkoBall(page: Page, amount: string): Promise<number> {
    const html   = await (await page.request.get(`${BASE_URL}/play/pachinko`)).text();
    const token  = html.match(/const CSRF_TOKEN='([^']+)'/)?.[1];
    const betUrl = html.match(/const BET_URL='([^']+)'/)?.[1];
    expect(token, 'pachinko page exposes its CSRF token').toBeTruthy();
    expect(betUrl, 'pachinko page exposes its bet URL').toBeTruthy();
    const res = await page.request.post(`${BASE_URL}${betUrl}`, { form: { _token: token!, amount } });
    expect(res.ok(), await res.text()).toBeTruthy();

    return parseFloat((await res.json()).payout);
}

function peso(amount: number): string {
    return `₱${amount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
}

test.describe('WFBO — Mini Games Leaderboard', () => {
    test.setTimeout(120_000);

    test('ranks a player by game and date range', async ({ page }) => {
        await ensurePachinkoEnabled(page);

        const player = await registerAndLogin(page);
        await loginAs(page, AUDITOR.mobile, AUDITOR.password);
        await adjustWalletAsAuditor(page, player.mobile, '100', 'Mini games leaderboard e2e');
        await loginAs(page, player.mobile, player.password);
        const payout = (await dropPachinkoBall(page, '10')) + (await dropPachinkoBall(page, '10'));

        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/games/report`);
        await page.click('[data-testid="wfbo-nav-games-leaderboard"]');
        await expect(page).toHaveURL(/\/wfbo\/games\/leaderboard$/);
        await expect(page.locator('[data-testid="mg-lb-info"]')).toContainText('All mini games');

        // Pachinko, ranked by Total Bet so a player who lost both drops still shows.
        await page.selectOption('[data-testid="mg-lb-game"]', 'pk');
        await page.selectOption('[data-testid="mg-lb-sort"]', 'total_bet');
        await page.click('[data-testid="mg-lb-apply"]');
        await expect(page).toHaveURL(/game=pk/);
        await expect(page).toHaveURL(/sort=total_bet/);

        const row = page.locator('[data-testid^="mg-lb-row-"]', { hasText: player.mobile });
        await expect(row).toHaveCount(1);
        await expect(row.locator('[data-testid^="mg-lb-bets-"]')).toHaveText('2');
        await expect(row).toContainText('₱20.00');
        await expect(row.locator('[data-testid^="mg-lb-winnings-"]')).toHaveText(peso(payout));
        await expect(row.locator('[data-testid^="mg-lb-net-"]')).toHaveText(peso(payout - 20));

        // All mini games: same player, Pachinko as their top game.
        await page.goto(`${BASE_URL}/wfbo/games/leaderboard?game=all&sort=total_bet&period=today`);
        const allRow = page.locator('[data-testid^="mg-lb-row-"]', { hasText: player.mobile });
        await expect(allRow).toHaveCount(1);
        await expect(allRow.locator('[data-testid^="mg-lb-top-game-"]')).toContainText('Pachinko');

        // Another game: the player never played it.
        await page.goto(`${BASE_URL}/wfbo/games/leaderboard?game=sw&sort=total_bet&period=today`);
        await expect(page.locator('[data-testid^="mg-lb-row-"]', { hasText: player.mobile })).toHaveCount(0);

        // A date range with no play.
        await page.goto(`${BASE_URL}/wfbo/games/leaderboard?game=pk&sort=total_bet&date_from=2020-01-01&date_to=2020-01-31`);
        await expect(page.locator('[data-testid="mg-lb-empty"]')).toBeVisible();
        await expect(page.locator('[data-testid="mg-lb-info"]')).toContainText('Jan 1 – Jan 31, 2020');
    });

    test('period pills keep the game and sort filters', async ({ page }) => {
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/games/leaderboard?game=fk&sort=win_count`);
        await page.click('[data-testid="mg-lb-period-last_month"]');
        await expect(page).toHaveURL(/game=fk/);
        await expect(page).toHaveURL(/sort=win_count/);
        await expect(page).toHaveURL(/period=last_month/);
        await expect(page.locator('[data-testid="mg-lb-info"]')).toContainText('Fruit King');
    });
});
