import { test, expect } from '@playwright/test';
import { testing_event_id } from './_helpers/env';
import {
    testing_exhibit_id,
    exhibit_staff_passcode,
    setup_leads_test_page,
} from './_helpers/leads_helpers';

const event_id = testing_event_id;
const exhibit_id = testing_exhibit_id;
const exhibit_url = `/events/${event_id}/leads/exhibit/${exhibit_id}`;

// ---------------------------------------------------------------------------
// Test license entries
// ---------------------------------------------------------------------------

/** A licensed staff member whose leads should be tagged with their email. */
const licensed_user = {
    full_name: 'Alice Staff',
    email: 'alice@acmecorp.com',
    passcode: 'ALICE99',
};

/** A second licensed user — verifies identity isolation between staff members. */
const licensed_user_b = {
    full_name: 'Bob Staff',
    email: 'bob@acmecorp.com',
    passcode: 'BOB88',
};

/**
 * license_li_json as a JSON string (matches how the API returns it and how
 * the sign-in component parses it inside handle_signin).
 */
const license_li_json = JSON.stringify([licensed_user, licensed_user_b]);

// Exhibit overrides that inject the license list into the mocked API response.
const exhibit_with_licenses = { license_li_json };

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

const signin_form = (page: Parameters<typeof expect>[0]) =>
    (page as import('@playwright/test').Page).locator('.exhibit-signin');

const header_action_btn = (page: Parameters<typeof expect>[0]) =>
    (page as import('@playwright/test').Page).locator(
        'header button.preset-filled-primary'
    );

const passcode_input = (page: Parameters<typeof expect>[0]) =>
    (page as import('@playwright/test').Page).locator(
        'input[placeholder="Enter shared code..."]'
    );

const search_mode_seed = { tab_add_mode: { [exhibit_id]: 'search' } };

/**
 * Navigate to the exhibit URL and wait for lq__exhibit_obj to be live in the
 * sign-in component before returning.
 *
 * The sign-in component's handle_signin() returns early if lq__exhibit_obj is
 * null. trusted_access causes handle_signin to auto-fill the shared passcode
 * input once lq__exhibit_obj loads — this is the same readiness signal used
 * in the shared passcode sign-in tests.
 *
 * Note: trusted_access does NOT bypass the auth gate (only manager_access
 * does), so the sign-in form will still appear for licensed user tests.
 */
async function goto_and_wait_for_exhibit_ready(
    page: import('@playwright/test').Page
): Promise<void> {
    await page.goto(exhibit_url);
    // Auto-fill fires once lq__exhibit_obj is live — this is our readiness signal.
    await expect(passcode_input(page)).toHaveValue(exhibit_staff_passcode, {
        timeout: 10_000,
    });
}

// ---------------------------------------------------------------------------
// Test suite
// ---------------------------------------------------------------------------

test.describe('Leads — Licensed User Sign-In', () => {
    // -----------------------------------------------------------------------
    // 1. Licensed user tab is visible on the sign-in form
    // -----------------------------------------------------------------------
    test('sign-in form has a Licensed User tab', async ({ page }) => {
        await setup_leads_test_page(page, event_id, exhibit_id, {
            exhibit_overrides: exhibit_with_licenses,
            access: { allow_access: true, trusted_access: true },
        });

        await page.goto(exhibit_url);

        await expect(signin_form(page)).toBeVisible({ timeout: 10_000 });
        await expect(page.locator('button:has-text("Licensed User")')).toBeVisible({
            timeout: 5_000,
        });
    });

    // -----------------------------------------------------------------------
    // 2. Correct email + passcode signs in successfully
    // -----------------------------------------------------------------------
    test('correct email and passcode signs in — form disappears, lead list shown', async ({ page }) => {
        await setup_leads_test_page(page, event_id, exhibit_id, {
            exhibit_overrides: exhibit_with_licenses,
            access: { allow_access: true, trusted_access: true },
        });

        await goto_and_wait_for_exhibit_ready(page);

        // Switch to Licensed User tab
        await page.locator('button:has-text("Licensed User")').click();

        await page.locator('input[type="email"]').fill(licensed_user.email);
        await page.locator('input[placeholder="Your code..."]').fill(licensed_user.passcode);
        await page.locator('button[type="submit"]').click();

        // After the 800 ms UX delay + reactivity, form should disappear
        await expect(signin_form(page)).not.toBeVisible({ timeout: 5_000 });
        await expect(header_action_btn(page)).toBeVisible({ timeout: 5_000 });
    });

    // -----------------------------------------------------------------------
    // 3. Wrong passcode shows error, form stays open
    // -----------------------------------------------------------------------
    test('wrong passcode shows error message, form stays visible', async ({ page }) => {
        await setup_leads_test_page(page, event_id, exhibit_id, {
            exhibit_overrides: exhibit_with_licenses,
            access: { allow_access: true, trusted_access: true },
        });

        await goto_and_wait_for_exhibit_ready(page);

        await page.locator('button:has-text("Licensed User")').click();
        await page.locator('input[type="email"]').fill(licensed_user.email);
        await page.locator('input[placeholder="Your code..."]').fill('WRONGCODE');
        await page.locator('button[type="submit"]').click();

        await expect(
            page.locator('text=Invalid email or personal passcode')
        ).toBeVisible({ timeout: 5_000 });
        await expect(signin_form(page)).toBeVisible({ timeout: 3_000 });
        await expect(header_action_btn(page)).not.toBeVisible();
    });

    // -----------------------------------------------------------------------
    // 4. Unknown email shows error, form stays open
    // -----------------------------------------------------------------------
    test('unknown email shows error message, form stays visible', async ({ page }) => {
        await setup_leads_test_page(page, event_id, exhibit_id, {
            exhibit_overrides: exhibit_with_licenses,
            access: { allow_access: true, trusted_access: true },
        });

        await goto_and_wait_for_exhibit_ready(page);

        await page.locator('button:has-text("Licensed User")').click();
        await page.locator('input[type="email"]').fill('unknown@notregistered.com');
        await page.locator('input[placeholder="Your code..."]').fill('ANYCODE');
        await page.locator('button[type="submit"]').click();

        await expect(
            page.locator('text=Invalid email or personal passcode')
        ).toBeVisible({ timeout: 5_000 });
        await expect(signin_form(page)).toBeVisible({ timeout: 3_000 });
    });

    // -----------------------------------------------------------------------
    // 5. Licensed user captures a lead — external_person_id = their email
    //
    // This is the core business rule: every lead captured by a licensed user
    // must be tagged with their email so "My Leads" filtering works per staff
    // member. The POST body is inspected directly to verify the identity field.
    // -----------------------------------------------------------------------
    test('lead captured by licensed user is tagged with their email address', async ({ page }) => {
        await setup_leads_test_page(page, event_id, exhibit_id, {
            exhibit_overrides: exhibit_with_licenses,
            access: { allow_access: true, trusted_access: true },
            leads_overrides: search_mode_seed,
        });

        await goto_and_wait_for_exhibit_ready(page);

        // Sign in as licensed user
        await page.locator('button:has-text("Licensed User")').click();
        await page.locator('input[type="email"]').fill(licensed_user.email);
        await page.locator('input[placeholder="Your code..."]').fill(licensed_user.passcode);
        await page.locator('button[type="submit"]').click();

        await expect(signin_form(page)).not.toBeVisible({ timeout: 5_000 });

        // Navigate to Add Lead tab
        await header_action_btn(page).click();

        const search_input = page.locator(
            'input[placeholder="Attendee name, email, or badge ID..."]'
        );
        await expect(search_input).toBeVisible({ timeout: 8_000 });
        await search_input.fill('Scott');
        await page.locator('button:has-text("Search")').click();
        await expect(page.locator('text=Scott Idem')).toBeVisible({ timeout: 8_000 });

        const create_promise = page.waitForRequest(
            (r) =>
                r.url().includes('event_exhibit_tracking') &&
                r.method() === 'POST',
            { timeout: 5_000 }
        );

        await page.locator('.results-list button.preset-filled-success').click();

        const create_req = await create_promise;
        const body = JSON.parse(create_req.postData() ?? '{}');

        // The lead must be tagged with the licensed user's email, not 'shared_passcode'
        expect(body.external_person_id).toBe(licensed_user.email);
        expect(body.group).toBe(licensed_user.email);
    });

    // -----------------------------------------------------------------------
    // 6. Two different licensed users get different external_person_id values
    //
    // Regression guard: Bob's leads must be tagged with his email, not Alice's
    // and not 'shared_passcode'.
    // -----------------------------------------------------------------------
    test('different licensed users are tagged with their own email addresses', async ({ page }) => {
        await setup_leads_test_page(page, event_id, exhibit_id, {
            exhibit_overrides: exhibit_with_licenses,
            access: { allow_access: true, trusted_access: true },
            leads_overrides: search_mode_seed,
        });

        await goto_and_wait_for_exhibit_ready(page);

        // Sign in as Bob (the second licensed user)
        await page.locator('button:has-text("Licensed User")').click();
        await page.locator('input[type="email"]').fill(licensed_user_b.email);
        await page.locator('input[placeholder="Your code..."]').fill(licensed_user_b.passcode);
        await page.locator('button[type="submit"]').click();

        await expect(signin_form(page)).not.toBeVisible({ timeout: 5_000 });

        await header_action_btn(page).click();

        const search_input = page.locator(
            'input[placeholder="Attendee name, email, or badge ID..."]'
        );
        await expect(search_input).toBeVisible({ timeout: 8_000 });
        await search_input.fill('Scott');
        await page.locator('button:has-text("Search")').click();
        await expect(page.locator('text=Scott Idem')).toBeVisible({ timeout: 8_000 });

        const create_promise = page.waitForRequest(
            (r) =>
                r.url().includes('event_exhibit_tracking') &&
                r.method() === 'POST',
            { timeout: 5_000 }
        );

        await page.locator('.results-list button.preset-filled-success').click();

        const create_req = await create_promise;
        const body = JSON.parse(create_req.postData() ?? '{}');

        // Must be Bob's email, not Alice's and not 'shared_passcode'
        expect(body.external_person_id).toBe(licensed_user_b.email);
        expect(body.external_person_id).not.toBe(licensed_user.email);
        expect(body.external_person_id).not.toBe('shared_passcode');
    });

    // -----------------------------------------------------------------------
    // 7. Pre-seeded licensed auth skips sign-in (returning user)
    //
    // A returning user whose session is already in auth_exhibit_kv with
    // type='licensed' should see the lead list directly — no sign-in form.
    // -----------------------------------------------------------------------
    test('pre-seeded licensed auth skips sign-in form', async ({ page }) => {
        await setup_leads_test_page(page, event_id, exhibit_id, {
            exhibit_overrides: exhibit_with_licenses,
            auth_kv: {
                // Simulate a returning session: already signed in as Alice
                [exhibit_id]: { key: licensed_user.email, type: 'licensed' },
            },
        });

        await page.goto(exhibit_url);

        await expect(signin_form(page)).not.toBeVisible({ timeout: 10_000 });
        await expect(header_action_btn(page)).toBeVisible({ timeout: 10_000 });
    });
});
