import { test, expect, Page } from '@playwright/test';
import {
    BASE_URL, ADMIN, FINANCE, loginAs, registerAndLogin, ensureMinesEnabled, playMinesRound,
    ensureLiveRacingEnabled, createArena, createEventShowUrl, addRace, addHorses,
    offerSingleBetTypes, publishEvent, placeWizardBet,
} from '../helpers';

test.describe('WFBO User Transactions & Wallet Adjustment', () => {

    async function navigateToFirstUserTransactions(page: Page) {
        await page.goto(`${BASE_URL}/wfbo/users`);
        const userRow = page.locator('[data-testid^="user-row-"]').first();
        await expect(userRow).toBeVisible();
        const rowId = (await userRow.getAttribute('data-testid'))?.replace('user-row-', '');
        await page.goto(`${BASE_URL}/wfbo/users/${rowId}/transactions`);
        return rowId;
    }

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

    test('navigating to user transactions shows user name', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await expect(page.locator('[data-testid="user-transactions-name"]')).toBeVisible();
    });

    test('user wallet balance is displayed', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await expect(page.locator('[data-testid="user-wallet-balance"]')).toBeVisible();
    });

    test('transactions table is visible on the user transactions page', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await expect(page.locator('[data-testid="user-transactions-table"]')).toBeVisible();
    });

    test('wallet adjustment form is visible', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await expect(page.locator('[data-testid="wallet-adjustment-form"]')).toBeVisible();
    });

    test('submitting a positive wallet adjustment shows flash-success and updates balance', async ({ page }) => {
        await navigateToFirstUserTransactions(page);

        const balanceBefore = await page.locator('[data-testid="user-wallet-balance"]').textContent();
        const beforeNum = parseFloat(balanceBefore?.replace(/[^\d.]/g, '') ?? '0');

        await page.fill('[data-testid="adj-amount"]', '50');
        await page.fill('[data-testid="adj-reason"]', 'Acceptance test credit');
        await page.click('[data-testid="adj-submit"]');

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

        const balanceAfter = await page.locator('[data-testid="user-wallet-balance"]').textContent();
        const afterNum = parseFloat(balanceAfter?.replace(/[^\d.]/g, '') ?? '0');
        expect(afterNum).toBeGreaterThan(beforeNum);
    });

    test('submitting a negative wallet adjustment shows flash-success and updates balance', async ({ page }) => {
        await navigateToFirstUserTransactions(page);

        // Credit first to ensure sufficient balance for debit
        await page.fill('[data-testid="adj-amount"]', '100');
        await page.fill('[data-testid="adj-reason"]', 'Pre-debit credit');
        await page.click('[data-testid="adj-submit"]');
        await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();

        const balanceBefore = await page.locator('[data-testid="user-wallet-balance"]').textContent();
        const beforeNum = parseFloat(balanceBefore?.replace(/[^\d.]/g, '') ?? '0');

        await page.fill('[data-testid="adj-amount"]', '-50');
        await page.fill('[data-testid="adj-reason"]', 'Acceptance test debit');
        await page.click('[data-testid="adj-submit"]');

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

        const balanceAfter = await page.locator('[data-testid="user-wallet-balance"]').textContent();
        const afterNum = parseFloat(balanceAfter?.replace(/[^\d.]/g, '') ?? '0');
        expect(afterNum).toBeLessThan(beforeNum);
    });

    test('submitting an adjustment that exceeds balance shows error', async ({ page }) => {
        await navigateToFirstUserTransactions(page);

        // Enter a huge negative adjustment
        await page.fill('[data-testid="adj-amount"]', '-9999999');
        await page.fill('[data-testid="adj-reason"]', 'Overdraft test');
        await page.click('[data-testid="adj-submit"]');

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

    test('period filters include this_year and last_year', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await expect(page.locator('[data-testid="period-this_year"]')).toBeVisible();
        await expect(page.locator('[data-testid="period-last_year"]')).toBeVisible();
    });

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

    test('bets tab shows user bets table card', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await page.click('[data-testid="tab-adjustments"]');
        await expect(page.locator('[data-testid="user-adjustments-table"]')).toBeVisible();
    });

    test('back to users link navigates back to /wfbo/users', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await page.click('[data-testid="btn-back-to-users"]');
        await expect(page).toHaveURL(`${BASE_URL}/wfbo/users`);
    });

    test('FINANCE user can view user transactions when navigated directly', async ({ page }) => {
        // Get a user ID from ADMIN context first
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        const rowId = await navigateToFirstUserTransactions(page);
        await expect(page.locator('[data-testid="user-transactions-name"]')).toBeVisible();

        // Now verify FINANCE can also access the same page directly
        await loginAs(page, FINANCE.mobile, FINANCE.password);
        await page.goto(`${BASE_URL}/wfbo/users/${rowId}/transactions`);
        await expect(page.locator('[data-testid="user-transactions-name"]')).toBeVisible();
    });

    test('Actions dropdown is visible on user transactions page for ADMIN', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await expect(page.locator('[data-testid="btn-actions"]')).toBeVisible();
    });

    test('Actions dropdown contains expected action items for ADMIN', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await page.click('[data-testid="btn-actions"]');
        // At minimum, reset password should always be visible for ADMIN
        await expect(page.locator('[data-testid="btn-reset-password"]')).toBeVisible();
    });

    test('Actions dropdown shows suspend/unsuspend based on user status', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await page.click('[data-testid="btn-actions"]');
        // Should see either suspend or unsuspend button (not both)
        const suspendBtn = page.locator('[data-testid="btn-suspend"]');
        const unsuspendBtn = page.locator('[data-testid="btn-unsuspend"]');
        const suspendVisible = await suspendBtn.isVisible().catch(() => false);
        const unsuspendVisible = await unsuspendBtn.isVisible().catch(() => false);
        expect(suspendVisible || unsuspendVisible).toBeTruthy();
    });

    test('Actions dropdown contains house win rate option', async ({ page }) => {
        await navigateToFirstUserTransactions(page);
        await page.click('[data-testid="btn-actions"]');
        await expect(page.locator('[data-testid="btn-house-win-rate"]')).toBeVisible();
    });

    test('bets tab shows a Mines row after the player completes a round', async ({ page }) => {
        await ensureMinesEnabled(page); // ends logged in as ADMIN

        const { mobile, password } = await registerAndLogin(page); // ends logged in as the fresh player

        // Credit the fresh player's wallet so they can afford the minimum Mines bet.
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/users?search=${encodeURIComponent(mobile)}`);
        const userRow = page.locator('[data-testid^="user-row-"]').first();
        await expect(userRow).toBeVisible();
        const userId = (await userRow.getAttribute('data-testid'))?.replace('user-row-', '');

        await page.goto(`${BASE_URL}/wfbo/users/${userId}/transactions`);
        await page.fill('[data-testid="adj-amount"]', '100');
        await page.fill('[data-testid="adj-reason"]', 'Acceptance test funding for Mines round');
        await page.click('[data-testid="adj-submit"]');
        await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();

        await loginAs(page, mobile, password);
        const played = await playMinesRound(page);
        expect(played).toBeTruthy();

        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/users/${userId}/transactions?type=bets`);
        await expect(page.locator('[data-testid^="bet-row-mines-"]').first()).toBeVisible();
    });

    test('the bets tab exports a player\'s Live Racing bets for a chosen day as a PDF', async ({ page }) => {
        await ensureLiveRacingEnabled(page); // ends logged in as ADMIN

        const arenaName = await createArena(page, 'LRExport', { win: '10.00' });
        const { eventUrl, eventId } = await createEventShowUrl(page, arenaName);
        const { raceUrl, raceId }   = await addRace(page, eventUrl, (Date.now() % 900) + 1);
        const horseIds = await addHorses(page, raceUrl, 2);
        await offerSingleBetTypes(page, eventUrl, [{ key: 'win', raceId }]);
        await publishEvent(page, eventUrl);

        const { mobile, password } = await registerAndLogin(page);

        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/users?search=${encodeURIComponent(mobile)}`);
        const userRow = page.locator('[data-testid^="user-row-"]').first();
        await expect(userRow).toBeVisible();
        const userId = (await userRow.getAttribute('data-testid'))?.replace('user-row-', '');
        await page.goto(`${BASE_URL}/wfbo/users/${userId}/transactions`);
        await page.fill('[data-testid="adj-amount"]', '100');
        await page.fill('[data-testid="adj-reason"]', 'Acceptance test funding for LR bet');
        await page.click('[data-testid="adj-submit"]');
        await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();

        await loginAs(page, mobile, password);
        await placeWizardBet(page, {
            eventId, raceId, cardLabel: 'Win', positions: { 1: [horseIds[0]] }, amount: '10',
        });

        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/users/${userId}/transactions?type=bets`);

        const exportForm = page.locator('[data-testid="lr-bets-export-form"]');
        await expect(exportForm).toBeVisible();
        const today = new Date().toISOString().slice(0, 10);
        await page.fill('[data-testid="lr-bets-export-date"]', today);

        const downloadPromise = page.waitForEvent('download');
        await page.click('[data-testid="btn-export-lr-bets"]');
        const download = await downloadPromise;
        expect(download.suggestedFilename()).toMatch(/^live-racing-bets-.*-\d{8}\.pdf$/);
    });

});
