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

test.describe('WFBO User Management', () => {

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

    test('users page loads with table', async ({ page }) => {
        await expect(page.locator('[data-testid="wfbo-sidebar"]')).toBeVisible();
        await expect(page.locator('[data-testid="users-table"]')).toBeVisible();
    });

    test('user rows are present', async ({ page }) => {
        const rows = page.locator('[data-testid^="user-row-"]');
        await expect(rows.first()).toBeVisible();
    });

    test('can suspend a user via actions dropdown', async ({ page }) => {
        // Own our target: a fresh player, so this never suspends a seeded staff
        // account that another spec depends on.
        const { mobile } = await registerAndLogin(page);

        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/users?search=${encodeURIComponent(mobile)}`);
        const row = page.locator('[data-testid^="user-row-"]').first();
        await expect(row).toBeVisible();
        const foundUserId = (await row.getAttribute('data-testid'))?.replace('user-row-', '') ?? null;
        if (!foundUserId) {
            test.skip();
            return;
        }
        await page.click(`[data-testid="btn-actions-${foundUserId}"]`);

        const suspendBtn = page.locator(`[data-testid="btn-suspend-${foundUserId}"]`);
        await expect(suspendBtn).toBeVisible();
        await suspendBtn.click();

        // Confirm the action in the confirmation modal
        const confirmBtn = page.locator('[data-testid="btn-confirm-action"]');
        await expect(confirmBtn).toBeVisible();
        await confirmBtn.click();

        await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
        await expect(page.locator(`[data-testid="badge-suspended-${foundUserId}"]`)).toBeVisible();
    });

    test('role filter dropdown is visible with all options', async ({ page }) => {
        const select = page.locator('select[name="role"]');
        await expect(select).toBeVisible();
        await expect(select.locator('option[value=""]')).toHaveText('All Roles');
        await expect(select.locator('option[value="ROLE_ADMIN"]')).toHaveText('Admin');
        await expect(select.locator('option[value="ROLE_MASTER_AGENT"]')).toHaveText('Master Agent');
        await expect(select.locator('option[value="ROLE_AGENT"]')).toHaveText('Agent');
        await expect(select.locator('option[value="ROLE_FINANCE"]')).toHaveText('Finance');
        await expect(select.locator('option[value="ROLE_OPERATIONS"]')).toHaveText('Operations');
        await expect(select.locator('option[value="ROLE_AUDITOR"]')).toHaveText('Auditor');
        await expect(select.locator('option[value="ROLE_USER"]')).toHaveText('User');
    });

    test('can filter users by role', async ({ page }) => {
        await page.selectOption('select[name="role"]', 'ROLE_USER');
        await page.click('button[type="submit"]');

        await expect(page).toHaveURL(/role=ROLE_USER/);
        await expect(page.locator('[data-testid="users-table"]')).toBeVisible();

        // All visible role badges should only show "User" (no special-role badges)
        const specialBadges = page.locator('.badge-role--admin, .badge-role--agent, .badge-role--agent-role, .badge-role--finance, .badge-role--operations');
        await expect(specialBadges).toHaveCount(0);
    });

    test('role filter persists across pagination', async ({ page }) => {
        await page.selectOption('select[name="role"]', 'ROLE_USER');
        await page.click('button[type="submit"]');
        await expect(page).toHaveURL(/role=ROLE_USER/);

        // If there's a next page, navigate to it and verify role param stays
        const nextBtn = page.locator('[data-testid="btn-next-page"]');
        if (await nextBtn.count() > 0) {
            await nextBtn.click();
            await expect(page).toHaveURL(/role=ROLE_USER/);
            await expect(page.locator('[data-testid="users-table"]')).toBeVisible();
        }
    });

    test('export to excel link is visible and carries the current filters', async ({ page }) => {
        const exportLink = page.locator('[data-testid="btn-export-users"]');
        await expect(exportLink).toBeVisible();
        await expect(exportLink).toHaveAttribute('href', /\/wfbo\/users\/export/);

        await page.selectOption('select[name="status"]', 'suspended');
        await page.click('button[type="submit"]');
        await expect(page).toHaveURL(/status=suspended/);

        await expect(page.locator('[data-testid="btn-export-users"]')).toHaveAttribute('href', /status=suspended/);
    });

    test('status filter dropdown is visible with all options', async ({ page }) => {
        const select = page.locator('select[name="status"]');
        await expect(select).toBeVisible();
        await expect(select.locator('option[value=""]')).toHaveText('All Statuses');
        await expect(select.locator('option[value="active"]')).toHaveText('Active');
        await expect(select.locator('option[value="suspended"]')).toHaveText('Suspended');
        await expect(select.locator('option[value="on_hold"]')).toHaveText('On Hold');
    });

    test('can filter users by status', async ({ page }) => {
        // Find any currently-active, non-staff user row (one that offers a
        // Suspend action) rather than registering a new one, so this test
        // doesn't depend on the registration flow. Suspend it, verify the
        // status filter, then unsuspend it again to leave state clean.
        const dropdownTriggers = page.locator('[data-testid^="btn-actions-"]');
        const triggerCount = await dropdownTriggers.count();
        let targetUserId: string | null = null;
        for (let i = 0; i < triggerCount; i++) {
            const trigger = dropdownTriggers.nth(i);
            const userId = (await trigger.getAttribute('data-testid'))?.replace('btn-actions-', '') ?? null;
            if (!userId) continue;

            await trigger.click();
            if (await page.locator(`[data-testid="btn-suspend-${userId}"]`).isVisible()) {
                targetUserId = userId;
                break;
            }
            // Close this row's dropdown before opening the next one - it stays
            // open otherwise and its menu intercepts clicks on later triggers.
            await page.keyboard.press('Escape');
        }
        if (!targetUserId) {
            test.skip();
            return;
        }

        await page.click(`[data-testid="btn-suspend-${targetUserId}"]`);
        await page.click('[data-testid="btn-confirm-action"]');
        await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();

        try {
            await page.goto(`${BASE_URL}/wfbo/users?status=suspended`);
            await expect(page.locator(`[data-testid="user-row-${targetUserId}"]`)).toBeVisible();
            await expect(page.locator(`[data-testid="badge-suspended-${targetUserId}"]`)).toBeVisible();

            await page.goto(`${BASE_URL}/wfbo/users?status=active`);
            await expect(page.locator(`[data-testid="user-row-${targetUserId}"]`)).toHaveCount(0);
        } finally {
            // Restore the user's original state for other tests in this run.
            // Unlike Suspend, Unsuspend submits its form directly (no confirm modal).
            await page.goto(`${BASE_URL}/wfbo/users?status=suspended`);
            await page.click(`[data-testid="btn-actions-${targetUserId}"]`);
            await page.click(`[data-testid="btn-unsuspend-${targetUserId}"]`);
            await expect(page.locator('[data-testid="flash-success"]')).toBeVisible();
        }
    });

    test('status filter persists across pagination', async ({ page }) => {
        await page.selectOption('select[name="status"]', 'active');
        await page.click('button[type="submit"]');
        await expect(page).toHaveURL(/status=active/);

        const nextBtn = page.locator('[data-testid="btn-next-page"]');
        if (await nextBtn.count() > 0) {
            await nextBtn.click();
            await expect(page).toHaveURL(/status=active/);
            await expect(page.locator('[data-testid="users-table"]')).toBeVisible();
        }
    });

    test('can sort users by wallet balance', async ({ page }) => {
        await page.click('[data-testid="sort-wallet"]');
        await expect(page).toHaveURL(/sort=wallet&dir=desc/);

        const descValues = await page.locator('[data-testid^="wallet-balance-"]').evaluateAll(
            cells => cells.map(el => parseFloat(el.getAttribute('data-value') ?? '0'))
        );
        const sortedDesc = [...descValues].sort((a, b) => b - a);
        expect(descValues).toEqual(sortedDesc);

        await page.click('[data-testid="sort-wallet"]');
        await expect(page).toHaveURL(/sort=wallet&dir=asc/);

        const ascValues = await page.locator('[data-testid^="wallet-balance-"]').evaluateAll(
            cells => cells.map(el => parseFloat(el.getAttribute('data-value') ?? '0'))
        );
        const sortedAsc = [...ascValues].sort((a, b) => a - b);
        expect(ascValues).toEqual(sortedAsc);
    });

    test('can promote a user to agent via actions dropdown', async ({ page }) => {
        // Find a user that has a promote-agent button, open their dropdown
        const promoteForm = page.locator('[data-testid^="form-promote-agent-"]').first();
        if (await promoteForm.count() === 0) {
            test.skip();
            return;
        }

        const formTestId = await promoteForm.getAttribute('data-testid');
        const userId = formTestId?.replace('form-promote-agent-', '');

        await page.locator(`[data-testid="btn-actions-${userId}"]`).click();
        const promoteBtn = page.locator(`[data-testid="btn-promote-agent-${userId}"]`);
        await expect(promoteBtn).toBeVisible();
        await promoteBtn.click();

        // Confirm the action in the confirmation modal
        const confirmBtn = page.locator('[data-testid="btn-confirm-action"]');
        await expect(confirmBtn).toBeVisible();
        await confirmBtn.click();

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

});
