import { test, expect } from '@playwright/test';
import { ae_app_local_data_defaults } from './_helpers/ae_defaults';
import { testing_event_id, testing_account_id } from './_helpers/env';

// Demo test data IDs from One Sky IT Demo environment
// Session: (703) "How To Do Things"
// Presentation: (1670) "Build a House"
// Presenter: (2202) "Bob The Builder"
const event_session_id = 'DOW3h7v6H42'; // Per README test data
const event_presentation_id = '7U2eXSjR6H4'; // Per README test data
const event_presenter_id = 'gT-hxnifb-0'; // Per README test data

test.describe('Cold-start: Event Session (IndexedDB empty)', () => {
  test.beforeEach(async ({ page }) => {
    page.on('pageerror', (err) => console.error(`BROWSER ERROR: ${err.message}`));
    page.on('console', (msg) => {
      if (msg.type() === 'error' || msg.type() === 'warning')
        console.error(`BROWSER [${msg.type().toUpperCase()}]: ${msg.text()}`);
    });

    // Provide app localStorage before any scripts run
    await page.addInitScript(
      ({ defaults, event_id, account_id }) => {
        const test_data = {
          ...defaults,
          account_id: account_id,
          administrator_access: true,
          trusted_access: true,
          authenticated_access: true,
          manager_access: false,
          super_access: false,
          edit_mode: true,
          mod_abstracts_json: {},
          person_id: 'QWODAPCNLQU', // Per README test data
          user: { id: 'QWODAPCNLQU' }, // Per README test data
          mod: { ...defaults.mod, events: { ...defaults.mod.events, event_id: event_id } }
        };
        window.localStorage.setItem('ae_loc', JSON.stringify(test_data));
      },
      { defaults: ae_app_local_data_defaults, event_id: testing_event_id, account_id: testing_account_id }
    );

    // Navigate to the application's origin so the page context is allowed
    // to access the IndexedDB API, then delete known Dexie DBs to simulate
    // a cold start.
    await page.goto('/');
    await page.evaluate(() => {
      const dbs = [
        'ae_events_db',
        'ae_journals_db',
        'ae_posts_db',
        'ae_archives_db',
        'ae_core_db',
        'ae_sponsorships_db'
      ];
      return Promise.all(
        dbs.map((name) =>
          new Promise((resolve) => {
            try {
              const req = indexedDB.deleteDatabase(name);
              req.onsuccess = () => resolve(true);
              req.onerror = () => resolve(false);
              req.onblocked = () => resolve(false);
            } catch (e) {
              resolve(false);
            }
          })
        )
      );
    });

    // Network mock: minimal responses for session, presentations, presenters
    await page.route('**/v3/crud/**', async (route) => {
      const req = route.request();
      const url = req.url();
      const method = req.method();

      // Session GET
      if (url.includes(`/v3/crud/event_session/${event_session_id}`) && method === 'GET') {
        return route.fulfill({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({
            data: {
              id: event_session_id,
              event_session_id: event_session_id,
              event_id: testing_event_id,
              name: 'How To Do Things',
              code: 'how-to-do-things',
              start_datetime: '2026-03-01T10:00:00Z',
              end_datetime: '2026-03-01T11:00:00Z',
              description: 'Cold start test session',
              event_location_id: 'VXXY-98-46-14', // Per README test data
              poc_person_id: 'QWODAPCNLQU', // Per README test data
              cfg_json: {},
              mod_pres_mgmt_json: {}
            }
          })
        });
      }

      // Presentations list for session
      if (url.includes('/v3/crud/event_presentation') && url.includes('for_obj_id') && url.includes(event_session_id) && method === 'GET') {
        return route.fulfill({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({
            data: [
              {
                id: event_presentation_id,
                event_presentation_id: event_presentation_id,
                event_session_id: event_session_id,
                event_id: testing_event_id,
                name: 'Build a House',
                code: 'build-house',
                start_datetime: '2026-03-01T10:00:00Z',
                end_datetime: '2026-03-01T10:30:00Z'
              }
            ]
          })
        });
      }

      // Presenters for "Build a House" presentation
      if (url.includes('/v3/crud/event_presenter') && url.includes(`for_obj_id=${event_presentation_id}`) && method === 'GET') {
        return route.fulfill({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({
            data: [
              {
                id: event_presenter_id,
                event_presenter_id: event_presenter_id,
                event_presentation_id: event_presentation_id,
                event_session_id: event_session_id,
                event_id: testing_event_id,
                given_name: 'Bob',
                family_name: 'The Builder',
                full_name: 'Bob The Builder',
                email: 'bob@builder.example.com'
              }
            ]
          })
        });
      }

      // Default: empty envelope
      return route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ data: [] })
      });
    });
  });

  test('renders Session with Presentations and Presenters on first load', async ({ page }) => {
    // Navigate directly to the session page (cold start - no IDB data)
    await page.goto(`/events/${testing_event_id}/session/${event_session_id}`);

    // 1. Verify session name is visible
    await expect(page.getByText('How To Do Things')).toBeVisible({ timeout: 10000 });

    // 2. Verify presentation is visible
    await expect(page.getByText('Build a House')).toBeVisible({ timeout: 5000 });

    // 3. CRITICAL: Verify presenter is visible WITHOUT manual refresh
    // This is the bug we're fixing - presenters should appear on first load
    await expect(page.getByText('Bob The Builder')).toBeVisible({ timeout: 10000 });

    // 4. Verify the presentations count display
    const presCountBadge = page.locator('text=/Presentations:/').locator('..').getByText('1');
    await expect(presCountBadge).toBeVisible({ timeout: 5000 });
  });

  test('verifies IndexedDB contains all nested data after load', async ({ page }) => {
    await page.goto(`/events/${testing_event_id}/session/${event_session_id}`);

    // Wait for data to be visible (indicating IDB writes completed)
    await expect(page.getByText('Bob The Builder')).toBeVisible({ timeout: 10000 });

    // Inspect IndexedDB to verify data integrity
    const idbData = await page.evaluate(async () => {
      const openDB = (name: string) => new Promise<IDBDatabase>((resolve, reject) => {
        const req = indexedDB.open(name);
        req.onsuccess = () => resolve(req.result);
        req.onerror = () => reject(req.error);
      });

      const getAllFromStore = (db: IDBDatabase, storeName: string) => new Promise<any[]>((resolve) => {
        const tx = db.transaction(storeName, 'readonly');
        const store = tx.objectStore(storeName);
        const req = store.getAll();
        req.onsuccess = () => resolve(req.result);
        req.onerror = () => resolve([]);
      });

      try {
        const db = await openDB('ae_events_db');
        const sessions = await getAllFromStore(db, 'session');
        const presentations = await getAllFromStore(db, 'presentation');
        const presenters = await getAllFromStore(db, 'presenter');
        db.close();

        return { sessions, presentations, presenters };
      } catch (e) {
        return { sessions: [], presentations: [], presenters: [], error: String(e) };
      }
    });

    // Verify data was written to IDB
    expect(idbData.sessions.length).toBeGreaterThan(0);
    expect(idbData.presentations.length).toBe(1);
    expect(idbData.presenters.length).toBe(1);

    // Verify presenter name is in IDB
    const presenterNames = idbData.presenters.map((p: any) => p.full_name);
    expect(presenterNames).toContain('Bob The Builder');
  });
});
