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

test.describe('Agent Portal — Insight', () => {

    test('a plain user cannot open the Insight page', async ({ page }) => {
        await loginAs(page, USER.mobile, USER.password);
        await page.goto(`${BASE_URL}/agent/insight`);
        await expect(page.locator('[data-testid="agent-insight-title"]')).not.toBeVisible();
    });

    test.describe('as a master agent', () => {
        test.beforeEach(async ({ page }) => {
            await loginAs(page, AGENT.mobile, AGENT.password);
        });

        test('the page loads with its title, nav link and headline tiles', async ({ page }) => {
            await page.goto(`${BASE_URL}/agent/insight`);

            await expect(page.locator('[data-testid="agent-insight-title"]')).toHaveText('Insight');
            await expect(page.locator('[data-testid="agent-nav-insight"]').first()).toBeVisible();

            for (const key of ['online', 'played', 'bets', 'wins', 'winrate', 'commission', 'deposits', 'withdrawals']) {
                await expect(page.locator(`[data-testid="stat-insight-${key}"]`)).toBeVisible();
            }
            // Players Win Rate reads as a percentage.
            await expect(page.locator('[data-testid="stat-insight-winrate"] .stat-value--lg')).toContainText('%');
            await expect(page.locator('[data-testid="agent-insight-online-table"]')).toBeVisible();
            await expect(page.locator('[data-testid="agent-insight-played-table"]')).toBeVisible();
            await expect(page.locator('[data-testid="agent-insight-requests-table"]')).toBeVisible();
            await expect(page.locator('[data-testid="agent-insight-direct-tx-table"]')).toBeVisible();
            await expect(page.locator('[data-testid="agent-insight-player-activity-table"]')).toBeVisible();
        });

        test('a past day: pick Yesterday → the tiles, Online and Played lists reflect that day; polling is off', async ({ page }) => {
            // Fixtures: "Weekly Referral" was seen + bet yesterday; "Recent"/"Earlier" only today.
            await page.goto(`${BASE_URL}/agent/insight?period=yesterday`);

            await expect(page.locator('[data-testid="agent-insight-day-yesterday"]')).toHaveClass(/is-active/);
            await expect(page.locator('[data-testid="agent-insight-snapshot-indicator"]')).toBeVisible();
            await expect(page.locator('[data-testid="stat-insight-online"] .stat-label--sm')).toContainText('Yesterday');

            const online = page.locator('[data-testid="agent-insight-online-table"]');
            const played = page.locator('[data-testid="agent-insight-played-table"]');
            await expect(online).toContainText('Weekly Referral');
            await expect(played).toContainText('Weekly Referral');
            await expect(online).not.toContainText('Recent Referral');
            await expect(played).not.toContainText('Recent Referral');

            // A past day never changes → the live poll is disabled.
            await expect(page.locator('[data-testid="agent-insight-live"]')).toHaveAttribute('data-agent-insight-live-value', 'false');
        });

        test('the day picker accepts an arbitrary date', async ({ page }) => {
            await page.goto(`${BASE_URL}/agent/insight?period=day_2026-08-15`);
            await expect(page.locator('[data-testid="agent-insight-title"]')).toBeVisible();
            await expect(page.locator('[data-testid="stat-insight-online"] .stat-label--sm')).toContainText('Aug 15, 2026');
            await expect(page.locator('[data-testid="agent-insight-day-input"]')).toHaveValue('2026-08-15');
        });

        test('the scope filter defaults to direct players and hides the sub-agent tx table', async ({ page }) => {
            await page.goto(`${BASE_URL}/agent/insight`);

            const directPill = page.locator('[data-testid="agent-insight-scope-direct"]');
            const allPill = page.locator('[data-testid="agent-insight-scope-all"]');
            await expect(directPill).toBeVisible();
            await expect(allPill).toBeVisible();
            await expect(directPill).toHaveClass(/is-active/);
            await expect(allPill).not.toHaveClass(/is-active/);

            await expect(page.locator('[data-testid="agent-insight-direct-tx-table"]')).toBeVisible();
            await expect(page.locator('[data-testid="agent-insight-subagent-tx-table"]')).toHaveCount(0);
        });

        test('switching to "All downlines" widens the scope and reveals the sub-agent tx table', async ({ page }) => {
            await page.goto(`${BASE_URL}/agent/insight`);
            await page.locator('[data-testid="agent-insight-scope-all"]').click();

            await expect(page).toHaveURL(/scope=all/);
            await expect(page.locator('[data-testid="agent-insight-scope-all"]')).toHaveClass(/is-active/);
            await expect(page.locator('[data-testid="agent-insight-subagent-tx-table"]')).toBeVisible();

            // The live-refresh URL carries the chosen scope so polling keeps the filter.
            await expect(page.locator('[data-testid="agent-insight-live"]'))
                .toHaveAttribute('data-agent-insight-url-value', /scope=all/);
        });

        test('the Player Activity table renders its columns', async ({ page }) => {
            await page.goto(`${BASE_URL}/agent/insight`);
            const table = page.locator('[data-testid="agent-insight-player-activity-table"]');
            await expect(table).toBeVisible();
            for (const heading of ['Player', 'Mobile', 'Last Deposit Request', 'Last Bet', 'Game']) {
                await expect(table.locator('thead th', { hasText: heading })).toBeVisible();
            }
        });

        test('the page wires up the auto-refresh controller', async ({ page }) => {
            await page.goto(`${BASE_URL}/agent/insight`);
            await expect(page.locator('[data-testid="agent-insight-live"][data-controller="agent-insight"]')).toBeAttached();
        });

        test('the live-data endpoint returns an HTML fragment', async ({ page }) => {
            await page.goto(`${BASE_URL}/agent/insight`);
            const res = await page.request.get(`${BASE_URL}/agent/insight/data`);
            expect(res.status()).toBe(200);
            expect(await res.text()).toContain('agent-insight-online-table');
        });

        test('the live-data endpoint honours the scope param for the sub-agent tx table', async ({ page }) => {
            await page.goto(`${BASE_URL}/agent/insight`);

            const all = await page.request.get(`${BASE_URL}/agent/insight/data?scope=all`);
            expect(all.status()).toBe(200);
            expect(await all.text()).toContain('agent-insight-subagent-tx-table');

            const direct = await page.request.get(`${BASE_URL}/agent/insight/data?scope=direct`);
            expect(direct.status()).toBe(200);
            expect(await direct.text()).not.toContain('agent-insight-subagent-tx-table');
        });
    });

    test('the online table paginates to 10 rows/page and keeps its page across a live refresh', async ({ page }) => {
        test.setTimeout(180_000);

        // 12 direct referrals of AGENT, all logged in during registration → all
        // "online today" in the default (direct) scope.
        for (let i = 0; i < 12; i++) {
            await registerUserWithReferralCode(page, 'ABCDEF01');
        }

        await loginAs(page, AGENT.mobile, AGENT.password);
        await page.goto(`${BASE_URL}/agent/insight`);

        const visibleRows = page.locator('[data-testid="agent-insight-online-table"] tbody tr.table-row:visible');
        const pager = page.locator('[data-insight-pager="agent-insight-online-table"]');

        await expect(visibleRows).toHaveCount(10);
        await expect(pager).toBeVisible();
        await expect(pager.locator('[data-insight-pager-info]')).toContainText('1–10 of');
        await expect(pager.locator('[data-insight-pager-prev]')).toBeDisabled();
        await expect(pager.locator('[data-insight-pager-next]')).toBeEnabled();

        await pager.locator('[data-insight-pager-next]').click();
        await expect(pager.locator('[data-insight-pager-info]')).toContainText('11–');
        await expect(pager.locator('[data-insight-pager-prev]')).toBeEnabled();

        // Survive one auto-refresh poll (interval is 15s).
        await page.waitForResponse((r) => r.url().includes('/agent/insight/data') && r.ok(), { timeout: 30_000 });
        await expect(pager.locator('[data-insight-pager-info]')).toContainText('11–');
        const visibleAfter = await visibleRows.count();
        expect(visibleAfter).toBeGreaterThan(0);
        expect(visibleAfter).toBeLessThanOrEqual(10);
    });

    test('a downline player active today appears in the online list', async ({ page }) => {
        const readOnline = async (): Promise<number> => {
            await loginAs(page, AGENT.mobile, AGENT.password);
            await page.goto(`${BASE_URL}/agent/insight`);
            const txt = (await page.locator('[data-testid="stat-insight-online"] .stat-value--lg').textContent()) ?? '';
            return parseInt(txt.trim(), 10) || 0;
        };

        const before = await readOnline();

        const player = await registerUserWithReferralCode(page, 'ABCDEF01');
        await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });

        await loginAs(page, AGENT.mobile, AGENT.password);
        await page.goto(`${BASE_URL}/agent/insight`);

        const after = parseInt(
            ((await page.locator('[data-testid="stat-insight-online"] .stat-value--lg').textContent()) ?? '').trim(),
            10,
        ) || 0;
        expect(after).toBeGreaterThanOrEqual(before + 1);
        await expect(
            page.locator('[data-testid="agent-insight-online-table"]').filter({ hasText: player.mobile }),
        ).toBeVisible();
    });
});
