import { test, expect } from '../../fixtures/supersync.fixture';
import {
  createTestUser,
  getSuperSyncConfig,
  createSimulatedClient,
  closeClient,
  markTaskDone,
  type SimulatedE2EClient,
} from '../../utils/supersync-helpers';
import { waitForAppReady } from '../../utils/waits';

/**
 * SuperSync Worklog/Archive E2E Tests
 *
 * Tests worklog and archive query scenarios:
 * - Archive tasks, query on other client
 * - Worklog data structure sync
 * - Multiple archives across clients
 */

test.describe('@supersync Worklog Sync', () => {
  /**
   * Test: Archived tasks appear in worklog on synced client
   *
   * Actions:
   * 1. Client A creates and completes tasks
   * 2. Client A archives via Finish Day
   * 3. Client A syncs
   * 4. Client B syncs
   * 5. Client B verifies tasks in worklog
   */
  test('Archived tasks appear in worklog on synced client', async ({
    browser,
    baseURL,
    testRunId,
  }) => {
    const uniqueId = Date.now();
    let clientA: SimulatedE2EClient | null = null;
    let clientB: SimulatedE2EClient | null = null;

    try {
      const user = await createTestUser(testRunId);
      const syncConfig = getSuperSyncConfig(user);

      // ============ PHASE 1: Client A Creates and Completes Tasks ============
      clientA = await createSimulatedClient(browser, baseURL!, 'A', testRunId);
      await clientA.sync.setupSuperSync(syncConfig);

      const task1Name = `Worklog1-${uniqueId}`;
      const task2Name = `Worklog2-${uniqueId}`;

      await clientA.workView.addTask(task1Name);
      await clientA.workView.addTask(task2Name);
      console.log('[Worklog Test] Client A created 2 tasks');

      // Mark both as done
      await markTaskDone(clientA, task1Name);
      await markTaskDone(clientA, task2Name);
      console.log('[Worklog Test] Client A marked tasks done');

      // ============ PHASE 2: Client A Archives ============
      const finishDayBtn = clientA.page.locator('.e2e-finish-day');
      await finishDayBtn.waitFor({ state: 'visible', timeout: 10000 });
      await finishDayBtn.click();

      await clientA.page.waitForURL(/daily-summary/, { timeout: 10000 });
      await clientA.page.waitForLoadState('networkidle');

      const saveBtn = clientA.page.locator(
        'daily-summary button[mat-flat-button]:has(mat-icon:has-text("wb_sunny"))',
      );
      await saveBtn.waitFor({ state: 'visible', timeout: 10000 });
      await saveBtn.click();

      await clientA.page.waitForURL(/tag\/TODAY/, { timeout: 10000 });
      console.log('[Worklog Test] Client A archived tasks');

      // ============ PHASE 3: Sync ============
      await clientA.sync.syncAndWait();
      console.log('[Worklog Test] Client A synced');

      // ============ PHASE 4: Client B Downloads and Checks Worklog ============
      clientB = await createSimulatedClient(browser, baseURL!, 'B', testRunId);
      await clientB.sync.setupSuperSync(syncConfig);
      await clientB.sync.syncAndWait();
      console.log('[Worklog Test] Client B synced');

      // Navigate to worklog
      await clientB.page.goto('/#/tag/TODAY/history');
      await clientB.page.waitForLoadState('networkidle');
      await clientB.page.waitForSelector('history', { timeout: 10000 });
      console.log('[Worklog Test] Client B navigated to worklog');

      // Expand week to see tasks
      const weekRow = clientB.page.locator('.week-row').first();
      if (await weekRow.isVisible()) {
        await weekRow.click();
        await clientB.page.waitForTimeout(500);
      }

      // Verify both tasks appear in worklog
      const task1InWorklog = clientB.page.locator(
        `.task-summary-table .task-title:has-text("${task1Name}")`,
      );
      const task2InWorklog = clientB.page.locator(
        `.task-summary-table .task-title:has-text("${task2Name}")`,
      );

      await expect(task1InWorklog).toBeVisible({ timeout: 10000 });
      await expect(task2InWorklog).toBeVisible({ timeout: 10000 });
      console.log('[Worklog Test] Both tasks visible in worklog on Client B');
    } finally {
      if (clientA) await closeClient(clientA);
      if (clientB) await closeClient(clientB);
    }
  });

  /**
   * Test: Worklog shows correct time data after sync
   *
   * Actions:
   * 1. Client A creates task, tracks time, completes
   * 2. Client A archives
   * 3. Client B syncs and checks worklog for time data
   */
  test('Worklog shows correct time data after sync', async ({
    browser,
    baseURL,
    testRunId,
  }) => {
    const uniqueId = Date.now();
    let clientA: SimulatedE2EClient | null = null;
    let clientB: SimulatedE2EClient | null = null;

    try {
      const user = await createTestUser(testRunId);
      const syncConfig = getSuperSyncConfig(user);

      // ============ PHASE 1: Client A Creates, Tracks, Completes ============
      clientA = await createSimulatedClient(browser, baseURL!, 'A', testRunId);
      await clientA.sync.setupSuperSync(syncConfig);

      const taskName = `TimedWorklog-${uniqueId}`;
      await clientA.workView.addTask(taskName);

      // Track time using helper functions (need to add imports)
      const task = clientA.page.locator(`task:has-text("${taskName}")`);
      await task.hover();
      await task.locator('.start-task-btn').click();
      await clientA.page.waitForTimeout(3000);
      await task.hover();
      const pauseBtn = task.locator('button:has(mat-icon:has-text("pause"))');
      await pauseBtn.click();
      console.log('[Timed Worklog Test] Tracked 3 seconds');

      // Complete task
      await markTaskDone(clientA, taskName);

      // ============ PHASE 2: Archive ============
      const finishDayBtn = clientA.page.locator('.e2e-finish-day');
      await finishDayBtn.waitFor({ state: 'visible', timeout: 10000 });
      await finishDayBtn.click();

      await clientA.page.waitForURL(/daily-summary/, { timeout: 10000 });

      const saveBtn = clientA.page.locator(
        'daily-summary button[mat-flat-button]:has(mat-icon:has-text("wb_sunny"))',
      );
      await saveBtn.waitFor({ state: 'visible', timeout: 10000 });
      await saveBtn.click();

      await clientA.page.waitForURL(/tag\/TODAY/, { timeout: 10000 });

      // ============ PHASE 3: Sync ============
      await clientA.sync.syncAndWait();

      // ============ PHASE 4: Client B Checks Worklog ============
      clientB = await createSimulatedClient(browser, baseURL!, 'B', testRunId);
      await clientB.sync.setupSuperSync(syncConfig);
      await clientB.sync.syncAndWait();

      await clientB.page.goto('/#/tag/TODAY/history');
      await clientB.page.waitForLoadState('networkidle');
      await clientB.page.waitForSelector('history', { timeout: 10000 });

      // Expand week
      const weekRow = clientB.page.locator('.week-row').first();
      if (await weekRow.isVisible()) {
        await weekRow.click();
        await clientB.page.waitForTimeout(500);
      }

      // Verify task appears in worklog
      const taskInWorklog = clientB.page.locator(`text=${taskName}`);
      await expect(taskInWorklog).toBeVisible({ timeout: 10000 });

      // The task with tracked time should appear in the worklog
      // Time data is stored but exact UI format varies
      console.log('[Timed Worklog Test] Task with time data visible in worklog');
    } finally {
      if (clientA) await closeClient(clientA);
      if (clientB) await closeClient(clientB);
    }
  });

  /**
   * Test: Multiple archive operations sync correctly
   *
   * Actions:
   * 1. Client A creates and archives tasks day 1
   * 2. Client A syncs
   * 3. Client B syncs
   * 4. Client B creates and archives more tasks
   * 5. Both sync
   * 6. Verify all archived tasks in worklog on both
   */
  test('Multiple archive operations sync correctly', async ({
    browser,
    baseURL,
    testRunId,
  }) => {
    const uniqueId = Date.now();
    let clientA: SimulatedE2EClient | null = null;
    let clientB: SimulatedE2EClient | null = null;

    try {
      const user = await createTestUser(testRunId);
      const syncConfig = getSuperSyncConfig(user);

      // ============ PHASE 1: Client A Archives First Batch ============
      clientA = await createSimulatedClient(browser, baseURL!, 'A', testRunId);
      await clientA.sync.setupSuperSync(syncConfig);

      const taskA1 = `BatchA1-${uniqueId}`;
      await clientA.workView.addTask(taskA1);

      await markTaskDone(clientA, taskA1);

      // Archive
      const finishDayBtnA = clientA.page.locator('.e2e-finish-day');
      await finishDayBtnA.click();
      await clientA.page.waitForURL(/daily-summary/, { timeout: 10000 });

      const saveBtnA = clientA.page.locator(
        'daily-summary button[mat-flat-button]:has(mat-icon:has-text("wb_sunny"))',
      );
      await saveBtnA.click();
      await clientA.page.waitForURL(/tag\/TODAY/, { timeout: 10000 });
      console.log('[Multi Archive Test] Client A archived first batch');

      await clientA.sync.syncAndWait();

      // ============ PHASE 2: Client B Archives Second Batch ============
      clientB = await createSimulatedClient(browser, baseURL!, 'B', testRunId);
      await clientB.sync.setupSuperSync(syncConfig);
      await clientB.sync.syncAndWait();

      const taskB1 = `BatchB1-${uniqueId}`;
      await clientB.workView.addTask(taskB1);

      await markTaskDone(clientB, taskB1);

      // Archive
      const finishDayBtnB = clientB.page.locator('.e2e-finish-day');
      await finishDayBtnB.click();
      await clientB.page.waitForURL(/daily-summary/, { timeout: 10000 });

      const saveBtnB = clientB.page.locator(
        'daily-summary button[mat-flat-button]:has(mat-icon:has-text("wb_sunny"))',
      );
      await saveBtnB.click();
      await clientB.page.waitForURL(/tag\/TODAY/, { timeout: 10000 });
      console.log('[Multi Archive Test] Client B archived second batch');

      // ============ PHASE 3: Sync Both ============
      await clientB.sync.syncAndWait();
      await clientA.sync.syncAndWait();
      console.log('[Multi Archive Test] Both synced');

      // Reload both clients to ensure archive data from sync is loaded
      // Archive data is stored in a separate IndexedDB store and may need reload to appear in UI
      await clientA.page.goto(clientA.page.url(), {
        waitUntil: 'domcontentloaded',
        timeout: 30000,
      });
      await waitForAppReady(clientA.page);
      await clientB.page.goto(clientB.page.url(), {
        waitUntil: 'domcontentloaded',
        timeout: 30000,
      });
      await waitForAppReady(clientB.page);
      console.log('[Multi Archive Test] Both clients reloaded after sync');

      // ============ PHASE 4: Verify All Archives in Worklog ============
      // Check Client A worklog
      await clientA.page.goto('/#/tag/TODAY/history');
      await clientA.page.waitForLoadState('networkidle');
      await clientA.page.waitForSelector('history', { timeout: 10000 });

      const weekRowA = clientA.page.locator('.week-row').first();
      if (await weekRowA.isVisible()) {
        await weekRowA.click();
        await clientA.page.waitForTimeout(500);
      }

      const taskA1InWorklog = clientA.page.locator(
        `.task-summary-table .task-title:has-text("${taskA1}")`,
      );
      const taskB1InWorklogA = clientA.page.locator(
        `.task-summary-table .task-title:has-text("${taskB1}")`,
      );

      await expect(taskA1InWorklog).toBeVisible({ timeout: 10000 });
      await expect(taskB1InWorklogA).toBeVisible({ timeout: 10000 });
      console.log('[Multi Archive Test] Client A has both archives in worklog');

      // Check Client B worklog
      await clientB.page.goto('/#/tag/TODAY/history');
      await clientB.page.waitForLoadState('networkidle');
      await clientB.page.waitForSelector('history', { timeout: 10000 });

      const weekRowB = clientB.page.locator('.week-row').first();
      if (await weekRowB.isVisible()) {
        await weekRowB.click();
        await clientB.page.waitForTimeout(500);
      }

      const taskA1InWorklogB = clientB.page.locator(
        `.task-summary-table .task-title:has-text("${taskA1}")`,
      );
      const taskB1InWorklog = clientB.page.locator(
        `.task-summary-table .task-title:has-text("${taskB1}")`,
      );

      await expect(taskA1InWorklogB).toBeVisible({ timeout: 10000 });
      await expect(taskB1InWorklog).toBeVisible({ timeout: 10000 });
      console.log('[Multi Archive Test] Client B has both archives in worklog');
    } finally {
      if (clientA) await closeClient(clientA);
      if (clientB) await closeClient(clientB);
    }
  });
});
