import { test, expect } from '@playwright/test';
import {
    BASE_URL, ADMIN, SUPER_ADMIN, loginAs, registerAndLogin, readWalletBalance,
    manila, windowAroundNow, createPaymentDetail, requestDeposit, approveNewestDepositOf,
} from '../helpers';

// Administration ▸ Deposit Campaigns (ROLE_SUPER_ADMIN): a player whose
// deposit is REQUESTED inside the campaign's daily window on one of its dates,
// for at least the minimum (approved amount), gets the bonus credited when the
// deposit is approved - at most once per player per day.

test.describe('WFBO Deposit Campaigns', () => {
    test.setTimeout(180_000);

    // Approve / disable use native confirm()s. One tolerant handler per page -
    // stacked page.once() handlers can race on the same dialog.
    test.beforeEach(async ({ page }) => {
        page.on('dialog', (d) => { d.accept().catch(() => {}); });
    });

    test('super admin configures a campaign; qualifying deposits earn the bonus once per day', async ({ page }) => {
        const name = `Morning Promo ${Date.now()}`;
        const bank = `Promo Bank ${Date.now()}`;
        const today = manila().date;
        const win = windowAroundNow();

        const player = await registerAndLogin(page);

        // Payment method without a finance handler, so ADMIN can approve.
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        const account = await createPaymentDetail(page, bank);

        // Super Admin creates the campaign from Campaigns ▸ Deposit Campaigns.
        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo`);
        await page.locator('button[aria-controls="campaigns-group-body"]').click();
        await page.locator('[data-testid="wfbo-nav-deposit-campaigns"]').click();
        await expect(page).toHaveURL(/\/wfbo\/deposit-campaigns$/);
        await page.click('[data-testid="btn-new-deposit-campaign"]');
        await expect(page.locator('[data-testid="input-dc-window-start"]')).toHaveValue('09:00');
        await expect(page.locator('[data-testid="input-dc-min-deposit"]')).toHaveValue('100');
        await expect(page.locator('[data-testid="input-dc-bonus-amount"]')).toHaveValue('20');
        await page.fill('[data-testid="input-dc-name"]', name);
        await page.fill('[data-testid="input-dc-start-date"]', today);
        await page.fill('[data-testid="input-dc-end-date"]', today);
        await page.fill('[data-testid="input-dc-window-start"]', win.start);
        await page.fill('[data-testid="input-dc-window-end"]', win.end);
        await page.click('[data-testid="btn-submit-deposit-campaign"]');
        await expect(page).toHaveURL(/\/wfbo\/deposit-campaigns$/);
        const row = page.locator('[data-testid^="deposit-campaign-row-"]', { hasText: name });
        const campaignId = ((await row.getAttribute('data-testid')) ?? '').replace('deposit-campaign-row-', '');
        await expect(page.locator(`[data-testid="deposit-campaign-status-${campaignId}"]`)).toHaveText(/active/i);

        // 1) ₱99 - under the minimum: no bonus.
        await loginAs(page, player.mobile, player.password);
        await requestDeposit(page, account, '99');
        let toast = await approveNewestDepositOf(page, player.mobile);
        expect(toast).not.toContain('Promo bonus');

        // 2) ₱100 - qualifies: +₱20.
        await loginAs(page, player.mobile, player.password);
        const before = await readWalletBalance(page);
        await requestDeposit(page, account, '100');
        toast = await approveNewestDepositOf(page, player.mobile);
        expect(toast).toContain(`Promo bonus ₱20.00 credited (${name})`);

        await loginAs(page, player.mobile, player.password);
        await page.goto(`${BASE_URL}/`);
        expect(await readWalletBalance(page)).toBeCloseTo(before + 120, 2);
        await page.goto(`${BASE_URL}/transactions`);
        await expect(page.locator('body')).toContainText(`Deposit promo bonus — ${name}`);

        // 3) Another qualifying deposit the same day: no second bonus.
        await requestDeposit(page, account, '300');
        toast = await approveNewestDepositOf(page, player.mobile);
        expect(toast).not.toContain('Promo bonus');

        // Deposits list badge + campaign totals / awards page.
        await page.goto(`${BASE_URL}/wfbo/deposits?status=approved&search=${encodeURIComponent(player.mobile)}`);
        await expect(page.locator('[data-testid^="badge-deposit-promo-"]')).toHaveCount(1);
        await expect(page.locator('[data-testid^="badge-deposit-promo-"]')).toHaveText('Promo +₱20.00');

        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns`);
        await expect(page.locator(`[data-testid="deposit-campaign-paid-${campaignId}"]`)).toHaveText('1 · ₱20.00');
        await page.click(`[data-testid="deposit-campaign-paid-${campaignId}"]`);
        await expect(page.locator('[data-testid^="deposit-campaign-award-"]')).toHaveCount(1);
        await expect(page.locator('[data-testid="deposit-campaign-awards-table"]')).toContainText(player.mobile);

        // Disable it so later specs aren't affected.
            await page.goto(`${BASE_URL}/wfbo/deposit-campaigns`);
        await page.click(`[data-testid="btn-toggle-deposit-campaign-${campaignId}"]`);
        await expect(page.locator(`[data-testid="deposit-campaign-status-${campaignId}"]`)).toHaveText(/disabled/i);
    });

    test('a campaign only pays on its selected weekdays', async ({ page }) => {
        const name = `Weekday Promo ${Date.now()}`;
        const bank = `Weekday Bank ${Date.now()}`;
        const today = manila().date;
        const win = windowAroundNow();
        // ISO weekday (1 = Mon … 7 = Sun) of today in Manila.
        const isoToday = ((new Date(`${today}T00:00:00Z`).getUTCDay() + 6) % 7) + 1;
        const labels = ['', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];

        const player = await registerAndLogin(page);
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        const account = await createPaymentDetail(page, bank);

        // Every day EXCEPT today.
        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns/new`);
        for (let d = 1; d <= 7; d++) {
            await expect(page.locator(`[data-testid="input-dc-day-${d}"]`)).toBeChecked();
        }
        await page.fill('[data-testid="input-dc-name"]', name);
        await page.fill('[data-testid="input-dc-start-date"]', today);
        await page.fill('[data-testid="input-dc-end-date"]', today);
        await page.fill('[data-testid="input-dc-window-start"]', win.start);
        await page.fill('[data-testid="input-dc-window-end"]', win.end);
        await page.locator(`[data-testid="input-dc-day-${isoToday}"]`).uncheck();
        await page.click('[data-testid="btn-submit-deposit-campaign"]');
        await expect(page).toHaveURL(/\/wfbo\/deposit-campaigns$/);

        const row = page.locator('[data-testid^="deposit-campaign-row-"]', { hasText: name });
        const campaignId = ((await row.getAttribute('data-testid')) ?? '').replace('deposit-campaign-row-', '');
        const daysCell = page.locator(`[data-testid="deposit-campaign-days-${campaignId}"]`);
        await expect(daysCell).not.toContainText(labels[isoToday]);

        // Qualifying deposit today, but today isn't a campaign day: no bonus.
        await loginAs(page, player.mobile, player.password);
        await requestDeposit(page, account, '100');
        let toast = await approveNewestDepositOf(page, player.mobile);
        expect(toast).not.toContain('Promo bonus');

        // Add today back (quick select "Every day"): the next deposit pays.
        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns/${campaignId}/edit`);
        await expect(page.locator(`[data-testid="input-dc-day-${isoToday}"]`)).not.toBeChecked();
        await page.click('[data-testid="dc-days-every"]');
        await expect(page.locator(`[data-testid="input-dc-day-${isoToday}"]`)).toBeChecked();
        await page.click('[data-testid="btn-submit-deposit-campaign"]');
        await expect(page.locator(`[data-testid="deposit-campaign-days-${campaignId}"]`)).toHaveText('Every day');

        await loginAs(page, player.mobile, player.password);
        await requestDeposit(page, account, '100');
        toast = await approveNewestDepositOf(page, player.mobile);
        expect(toast).toContain(`Promo bonus ₱20.00 credited (${name})`);

        // Leave nothing enabled for later specs.
        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns`);
            await page.click(`[data-testid="btn-toggle-deposit-campaign-${campaignId}"]`);
        await expect(page.locator(`[data-testid="deposit-campaign-status-${campaignId}"]`)).toHaveText(/disabled/i);
    });

    test('at least one weekday is required', async ({ page }) => {
        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns/new`);
        for (let d = 1; d <= 7; d++) {
            await page.locator(`[data-testid="input-dc-day-${d}"]`).uncheck();
        }
        await page.click('[data-testid="btn-submit-deposit-campaign"]');
        await expect(page.locator('[data-testid="flash-error"]').filter({ hasText: 'Select at least one day' })).toHaveCount(1);
    });

    test('form validation errors are shown', async ({ page }) => {
        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns/new`);
        await page.fill('[data-testid="input-dc-name"]', '');
        await page.fill('[data-testid="input-dc-window-start"]', '12:00');
        await page.fill('[data-testid="input-dc-window-end"]', '09:00');
        await page.click('[data-testid="btn-submit-deposit-campaign"]');

        const errors = page.locator('[data-testid="flash-error"]');
        for (const msg of ['Campaign name is required', 'Start and end dates are required', 'Daily end time must be after the start time']) {
            await expect(errors.filter({ hasText: msg })).toHaveCount(1);
        }
    });

    test('effectiveness report compares the campaign with a baseline and shows bonus economics', async ({ page }, testInfo) => {
        const player = await registerAndLogin(page);
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        const account = await createPaymentDetail(page, `Report Bank ${Date.now()}`);

        const today = manila().date;
        const win   = windowAroundNow();
        const name  = `Report Promo ${Date.now()}`;
        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns/new`);
        await page.fill('[data-testid="input-dc-name"]', name);
        await page.fill('[data-testid="input-dc-start-date"]', today);
        await page.fill('[data-testid="input-dc-end-date"]', today);
        await page.fill('[data-testid="input-dc-window-start"]', win.start);
        await page.fill('[data-testid="input-dc-window-end"]', win.end);
        await page.click('[data-testid="btn-submit-deposit-campaign"]');
        const row = page.locator('[data-testid^="deposit-campaign-row-"]', { hasText: name });
        const campaignId = ((await row.getAttribute('data-testid')) ?? '').replace('deposit-campaign-row-', '');

        // A qualifying ₱200 deposit earns the ₱20 bonus.
        await loginAs(page, player.mobile, player.password);
        await requestDeposit(page, account, '200');
        expect(await approveNewestDepositOf(page, player.mobile)).toContain('Promo bonus ₱20.00 credited');

        // Campaigns ▸ Deposit Campaigns ▸ Report.
        await loginAs(page, SUPER_ADMIN.mobile, SUPER_ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns`);
        await page.click(`[data-testid="btn-report-deposit-campaign-${campaignId}"]`);
        await expect(page).toHaveURL(new RegExp(`/wfbo/deposit-campaigns/${campaignId}/report$`));

        await expect(page.locator('[data-testid="dcr-verdict-badge"]')).toHaveText(/effective|mixed|not effective/i);
        await expect(page.locator('[data-testid="dcr-verdict-reasons"] li').first()).toContainText('Approved deposits in the campaign hours');
        await expect(page.locator('[data-testid="dcr-periods"]')).toContainText('the same weekdays right before the campaign');
        await expect(page.locator('[data-testid="dcr-bonus-cost"]')).toHaveText('₱20.00');
        await expect(page.locator('[data-testid="dcr-chart"] canvas')).toBeVisible();
        const windowRequests = Number(await page.locator('[data-testid="dcr-requests-campaign"]').textContent());
        expect(windowRequests).toBeGreaterThanOrEqual(1);

        // The awarded player, what they did after the bonus.
        const playerRow = page.locator('[data-testid^="dcr-player-"]', { hasText: player.mobile });
        await expect(playerRow).toBeVisible();
        await expect(playerRow).toContainText('₱200.00');   // deposited
        await expect(playerRow).toContainText('Reactivated'); // brand-new player: no baseline deposit
        await expect(playerRow.locator('[data-testid^="dcr-player-net-"]')).toHaveText('-₱20.00'); // no play yet
        await page.waitForTimeout(1500); // let the chart finish its draw-in animation
        await page.screenshot({ path: testInfo.outputPath('deposit-campaign-report.png'), fullPage: true });

        // Compare with a custom date range instead.
        await page.fill('[data-testid="dcr-compare-from"]', '2026-01-01');
        await page.fill('[data-testid="dcr-compare-to"]', '2026-01-31');
        await page.click('[data-testid="dcr-compare-submit"]');
        await expect(page).toHaveURL(/compare_from=2026-01-01&compare_to=2026-01-31/);
        await expect(page.locator('[data-testid="dcr-periods"]')).toContainText('custom range');
        await expect(page.locator('[data-testid="dcr-periods"]')).toContainText('Jan 1');

        // Clean up so later specs aren't affected.
        await page.goto(`${BASE_URL}/wfbo/deposit-campaigns`);
        await page.click(`[data-testid="btn-toggle-deposit-campaign-${campaignId}"]`);
        await expect(page.locator(`[data-testid="deposit-campaign-status-${campaignId}"]`)).toHaveText(/disabled/i);
    });

    test('a regular admin has no access', async ({ page }) => {
        await loginAs(page, ADMIN.mobile, ADMIN.password);
        await page.goto(`${BASE_URL}/wfbo`);
        await expect(page.locator('[data-testid="wfbo-nav-deposit-campaigns"]')).toHaveCount(0);
        const res = await page.goto(`${BASE_URL}/wfbo/deposit-campaigns`);
        expect(res?.status()).toBe(403);
        const report = await page.goto(`${BASE_URL}/wfbo/deposit-campaigns/1/report`);
        expect(report?.status()).toBe(403);
    });
});
