import { test, expect, type Page } from '@playwright/test';
import {
    BASE_URL,
    ADMIN,
    FINANCE,
    OPERATIONS,
    loginAs,
    registerAndLogin,
    adjustWalletAsAdmin,
    ensureMinesEnabled,
} from '../helpers';

test.describe('WFBO Dashboard', () => {

    test.beforeEach(async ({ page }) => {
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo`);
    });

    test('dashboard loads with total-users stat card', async ({ page }) => {
        await expect(page.locator('[data-testid="stat-total-users"]')).toBeVisible();
    });

    test('dashboard shows pending deposits stat card', async ({ page }) => {
        await expect(page.locator('[data-testid="stat-pending-deposits"]')).toBeVisible();
    });

    test('dashboard shows pending withdrawals stat card', async ({ page }) => {
        await expect(page.locator('[data-testid="stat-pending-withdrawals"]')).toBeVisible();
    });

    test('period filter buttons are present', async ({ page }) => {
        const filters = page.locator('[data-testid^="period-"]');
        await expect(filters.first()).toBeVisible();
        const count = await filters.count();
        expect(count).toBeGreaterThanOrEqual(6); // today, yesterday, this_month, last_month, this_year, last_year
    });

    test('dashboard refresh button is visible', async ({ page }) => {
        await expect(page.locator('[data-testid="btn-dashboard-refresh"]')).toBeVisible();
    });

    test('clicking last_year period filter reloads and stat cards remain visible', async ({ page }) => {
        await page.click('[data-testid="period-last_year"]');
        await page.waitForLoadState('networkidle');
        await expect(page.locator('[data-testid="stat-total-users"]')).toBeVisible();
        await expect(page.locator('[data-testid="stat-gameCount"]')).toBeVisible();
    });

    test('clicking this_month period filter reloads and stat cards remain visible', async ({ page }) => {
        await page.click('[data-testid="period-this_month"]');
        await page.waitForLoadState('networkidle');
        await expect(page.locator('[data-testid="stat-total-users"]')).toBeVisible();
        await expect(page.locator('[data-testid="stat-gameCount"]')).toBeVisible();
    });

    test('game count stat card is visible', async ({ page }) => {
        await expect(page.locator('[data-testid="stat-gameCount"]')).toBeVisible();
    });

    test('deposit requests split-stat card is visible', async ({ page }) => {
        await expect(page.locator('[data-testid="stat-deposit-requests"]')).toBeVisible();
    });

    test('withdrawal requests split-stat card is visible', async ({ page }) => {
        await expect(page.locator('[data-testid="stat-withdrawal-requests"]')).toBeVisible();
    });

    test('FINANCE user can access the dashboard', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        // FINANCE sees pending deposits/withdrawals, not total-users (ROLE_OPERATIONS only)
        await expect(page.locator('[data-testid="stat-pending-deposits"]')).toBeVisible();
    });

    test('OPERATIONS user can access the dashboard', async ({ page }) => {
        await loginAs(page, OPERATIONS.mobile, OPERATIONS.password);
        await page.goto(`${BASE_URL}/wfbo`);
        await expect(page.locator('[data-testid="stat-total-users"]')).toBeVisible();
    });

    test('plain USER is blocked from /wfbo (no WFBO sidebar visible)', async ({ page }) => {
        // Use a fresh registration so this user has no roles that could be promoted by other tests
        await page.context().clearCookies();
        await registerAndLogin(page);
        await page.goto(`${BASE_URL}/wfbo`);
        // Whether Symfony redirects or returns 403, the WFBO sidebar must not appear
        await expect(page.locator('[data-testid="wfbo-sidebar"]')).not.toBeVisible();
    });

    test('financial chart card is visible for FINANCE user', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        await expect(page.locator('[data-testid="wfbo-financial-chart"]')).toBeVisible();
    });

    test('net revenue trend chart card is visible for FINANCE user', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        await expect(page.locator('[data-testid="wfbo-revenue-trend-chart"]')).toBeVisible();
        await expect(page.locator('[data-testid="wfbo-revenue-trend-chart"] canvas')).toBeVisible();
    });

    test('pending-status API returns JSON with required fields', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        const response = await page.request.get(`${BASE_URL}/wfbo/pending-status`);
        expect(response.status()).toBe(200);
        const data = await response.json();
        expect(data).toHaveProperty('pendingDeposits');
        expect(data).toHaveProperty('pendingWithdrawals');
        expect(data).toHaveProperty('cashOnHand');
        expect(data).toHaveProperty('totalPlayerBalance');
        expect(typeof data.pendingDeposits).toBe('number');
        expect(typeof data.pendingWithdrawals).toBe('number');
        expect(typeof data.cashOnHand).toBe('number');
    });

    test('cash on hand card indicates it resets every month (This month label)', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        await expect(page.locator('[data-testid="stat-cash-on-hand"]')).toBeVisible();
        await expect(page.locator('[data-testid="stat-cash-on-hand"]')).toContainText('This month');
    });

    test('dashboard-chart API returns JSON with labels and data arrays', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        const response = await page.request.get(`${BASE_URL}/wfbo/dashboard-chart?period=today`);
        expect(response.status()).toBe(200);
        const data = await response.json();
        expect(data).toHaveProperty('labels');
        expect(data).toHaveProperty('deposits');
        expect(data).toHaveProperty('withdrawals');
        expect(Array.isArray(data.labels)).toBe(true);
        expect(Array.isArray(data.deposits)).toBe(true);
        expect(Array.isArray(data.withdrawals)).toBe(true);
        expect(data.labels.length).toBe(data.deposits.length);
        expect(data.labels.length).toBe(data.withdrawals.length);
    });

    test('pending deposits stat card has live-update data target attribute', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        await expect(page.locator('[data-wfbo-pending-target="pendingDepositsValue"]')).toBeAttached();
        await expect(page.locator('[data-wfbo-pending-target="pendingWithdrawalsValue"]')).toBeAttached();
    });

    test('finance stat cards include a Mines (MN) per-game breakdown', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        await expect(page.locator('[data-testid="stat-betAmount"]')).toContainText('MN:');
        await expect(page.locator('[data-testid="stat-commissions"]')).toContainText('MN:');
        await expect(page.locator('[data-testid="stat-revenue"]')).toContainText('MN:');
        await expect(page.locator('[data-testid="stat-winAmount"]')).toContainText('MN:');
        await expect(page.locator('[data-testid="stat-winLooseRate"]')).toContainText('MN:');
    });

    test('per-game breakdown renders as badges, not divider-separated text', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo`);
        const betAmountBadges = page.locator('[data-testid="stat-betAmount"] .stat-game-badge');
        await expect(betAmountBadges).toHaveCount(4);
        await expect(betAmountBadges.first()).toContainText('VK:');
        await expect(page.locator('[data-testid="stat-betAmount"] .stat-game-divider')).toHaveCount(0);
    });

});

test.describe('WFBO Dashboard — Active Players counts every game', () => {
    test.setTimeout(180_000);

    async function readActivePlayers(page: Page): Promise<number> {
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo?period=today`);
        const txt = (await page.locator('[data-testid="stat-activePlayers-value"]').textContent()) ?? '';
        return parseInt(txt.trim(), 10) || 0;
    }

    test('a non-VK game bet makes the player count as active', async ({ page }) => {
        // Fresh player, funded. Mines stands in for "any game that isn't VK
        // race betting" - the old metric only counted race_bet rows. Starting a
        // round is enough: it deducts the stake and writes the mines_game row.
        const player = await registerAndLogin(page);
        await adjustWalletAsAdmin(page, player.mobile, '500.00', 'active-players test');
        await ensureMinesEnabled(page);

        const before = await readActivePlayers(page);

        await loginAs(page, player.mobile, player.password);
        await page.goto(`${BASE_URL}/play/mines`, { waitUntil: 'domcontentloaded' });
        await page.locator('[data-testid="mg-bet-chip"][data-amount="5"]').click();
        await page.locator('[data-testid="mg-tier-green"]').click();
        await page.click('[data-testid="btn-mg-start"]');
        await expect(page.locator('[data-testid="btn-mg-cashout"]')).toBeVisible();

        const after = await readActivePlayers(page);
        expect(after).toBeGreaterThanOrEqual(before + 1);
    });
});
