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

test.describe('WFBO Report (Cash Flow) — AUDITOR access', () => {

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

    test('report page loads with stat cards', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="stat-cash-in"]')).toBeVisible();
        await expect(page.locator('[data-testid="stat-cash-out"]')).toBeVisible();
        await expect(page.locator('[data-testid="stat-cash-on-hand"]')).toBeVisible();
    });

    test('the deposit/withdrawal cards are labelled Total Deposits/Total Withdrawals and show a pending line', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);

        const depositsCard = page.locator('[data-testid="stat-cash-in"]');
        await expect(depositsCard).toContainText('Total Deposits');
        await expect(depositsCard).not.toContainText('Cash In');
        const pendingDeposits = page.locator('[data-testid="stat-deposits-pending"]');
        await expect(pendingDeposits).toContainText('Pending');
        await expect(pendingDeposits).toContainText('₱');

        const withdrawalsCard = page.locator('[data-testid="stat-cash-out"]');
        await expect(withdrawalsCard).toContainText('Total Withdrawals');
        await expect(withdrawalsCard).not.toContainText('Cash Out');
        const pendingWithdrawals = page.locator('[data-testid="stat-withdrawals-pending"]');
        await expect(pendingWithdrawals).toContainText('Pending');
        await expect(pendingWithdrawals).toContainText('₱');
    });

    test('the "Net Cash Flow" tally is no longer shown', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="stat-net-period"]')).toHaveCount(0);
        await expect(page.locator('body')).not.toContainText('Net Cash Flow');
    });

    test('page heading reads "Report"', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="wfbo-page-title"]')).toHaveText('Report');
    });

    test('cash on hand card is scoped to the selected period, not all-time', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        const periodLabel = page.locator('[data-testid="stat-cash-on-hand"] .stat-sub').first();
        await expect(periodLabel).toHaveText(/^(January|February|March|April|May|June|July|August|September|October|November|December) \d{4}$/);
        await expect(page.locator('[data-testid="stat-cash-on-hand"]')).not.toContainText('All-time');

        // The Cash on Hand row in the summary breakdown table is period-scoped too.
        await expect(page.locator('body')).not.toContainText('All-time');
    });

    test('the PDF export button is gone', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="btn-export-pdf"]')).toHaveCount(0);
        const response = await page.request.get(`${BASE_URL}/wfbo/cashflow/export`);
        expect(response.status()).toBe(404);
    });

    test('period filter buttons are present', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="period-this_month"]').first()).toBeVisible();
    });

    test('approved deposits by loader table is present with an Unassigned row and a Total row', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        const table = page.locator('[data-testid="finance-handler-breakdown"]');
        await expect(table).toBeVisible();
        await expect(table).toContainText('Approved Deposits');
        await expect(page.locator('[data-testid="finance-handler-row-unassigned"]')).toContainText('Unassigned / Other');

        const totalRow = page.locator('[data-testid="finance-handler-row-total"]');
        await expect(totalRow).toContainText('Total');
        await expect(totalRow).toContainText('₱');
    });

    test('approved withdrawals by approver table is present with Unassigned and Total rows', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        const table = page.locator('[data-testid="withdrawal-approver-breakdown"]');
        await expect(table).toBeVisible();
        await expect(table).toContainText('Approved Withdrawals');
        await expect(page.locator('[data-testid="withdrawal-approver-row-unassigned"]')).toContainText('Unassigned / Other');

        const totalRow = page.locator('[data-testid="withdrawal-approver-row-total"]');
        await expect(totalRow).toContainText('Total');
        await expect(totalRow).toContainText('₱');
    });

    test('system adjustments by staff member table is present with a Total row', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        const table = page.locator('[data-testid="adjustment-breakdown"]');
        await expect(table).toBeVisible();
        await expect(table).toContainText('Net Amount');

        const totalRow = page.locator('[data-testid="adjustment-row-total"]');
        await expect(totalRow).toContainText('Total');
        await expect(totalRow).toContainText('₱');
    });

    test('expenses table is present with a Total row', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow?period=this_year`);
        const table = page.locator('[data-testid="expense-breakdown"]');
        await expect(table).toBeVisible();
        await expect(table).toContainText('Description');

        const totalRow = page.locator('[data-testid="expense-report-row-total"]');
        await expect(totalRow).toContainText('Total');
        await expect(totalRow).toContainText('₱');
    });

    test('the summary flow deducts expenses from Cash on Hand', async ({ page }) => {
        await page.goto(`${BASE_URL}/wfbo/cashflow?period=this_year`);

        const expensesRow = page.locator('[data-testid="summary-expenses-row"]');
        await expect(expensesRow).toContainText('Expenses');
        await expect(expensesRow).toContainText('₱');

        // Cash on Hand = deposits in − withdrawals out − expenses.
        const num = async (loc: ReturnType<typeof page.locator>) =>
            Number(((await loc.textContent()) ?? '').replace(/[^0-9.-]/g, '') || '0');

        const rows = page.locator('table').first().locator('tbody tr');
        const cashIn = await num(rows.nth(0).locator('td').last());
        const cashOut = await num(rows.nth(1).locator('td').last());
        const expenses = await num(expensesRow.locator('td').last());
        const cashOnHand = await num(rows.nth(3).locator('td').last());

        expect(Math.round(cashOnHand * 100)).toBe(Math.round((cashIn - cashOut - expenses) * 100));
    });

    test('an adjustment made by the auditor shows up in the Report breakdown', async ({ page }) => {
        const { mobile } = await registerAndLogin(page);

        await adjustWalletAsAuditor(page, mobile, '250', 'report breakdown check');

        await loginAs(page, AUDITOR.mobile, AUDITOR.password);
        await page.goto(`${BASE_URL}/wfbo/cashflow?period=today`);

        const table = page.locator('[data-testid="adjustment-breakdown"]');
        await expect(table).toContainText('Auditor');
        await expect(page.locator('[data-testid="adjustment-row-total"]')).not.toContainText('₱0.00');
    });

});

test.describe('WFBO Report (Cash Flow) — role guard', () => {

    test('AUDITOR user can access the report and sees the "Report" nav link', async ({ page }) => {
        await loginAs(page, AUDITOR.mobile, AUDITOR.password);
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="stat-cash-in"]')).toBeVisible();
        await expect(page.locator('[data-testid="wfbo-nav-cashflow"]')).toContainText('Report');
    });

    test('a plain ADMIN (no auditor role) is blocked from the report and has no nav link', async ({ page }) => {
        await loginAs(page, ADMIN.mobile, ADMIN.password);

        // Other WFBO pages are still reachable...
        await page.goto(`${BASE_URL}/wfbo/deposits`);
        await expect(page.locator('[data-testid="wfbo-nav-deposits"]')).toBeVisible();
        await expect(page.locator('[data-testid="wfbo-nav-cashflow"]')).toHaveCount(0);

        // ...but the report page itself is denied.
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="stat-cash-in"]')).not.toBeVisible();
    });

    test('FINANCE user is blocked from the report and has no nav link', async ({ page }) => {
        await loginAs(page, FINANCE.mobile, FINANCE.password);

        await page.goto(`${BASE_URL}/wfbo/deposits`);
        await expect(page.locator('[data-testid="wfbo-nav-deposits"]')).toBeVisible();
        await expect(page.locator('[data-testid="wfbo-nav-cashflow"]')).toHaveCount(0);

        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="stat-cash-in"]')).not.toBeVisible();
    });

    test('OPERATIONS user is blocked from the report', async ({ page }) => {
        await loginAs(page, OPERATIONS.mobile, OPERATIONS.password);
        await page.goto(`${BASE_URL}/wfbo/cashflow`);
        await expect(page.locator('[data-testid="stat-cash-in"]')).not.toBeVisible();
    });

});
