import { test, expect } from '@playwright/test';
import { loginToJamUI, createAndJoinSession } from '../utils/test-helpers';

test.describe('Chat Unread Badge', () => {
  test.beforeEach(async ({ page }) => {
    await loginToJamUI(page);
    await createAndJoinSession(page);
  });

  test('badge hidden when count is 0', async ({ page }) => {
    // Wait for session to load
    await page.waitForTimeout(1000);

    // Get session ID from Redux store
    const sessionId = await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      return store.getState().sessionState?.sessionId || 'test-session-id';
    });

    // Badge should be hidden when no unread messages
    const badge = page.locator('div').filter({ hasText: /^\d+$/ }).first();
    await expect(badge).toBeHidden();
  });

  test('badge shows count when message arrives with window closed', async ({ page }) => {
    await page.waitForTimeout(1000);

    // Get session ID
    const sessionId = await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      return store.getState().sessionState?.sessionId || 'test-session-id';
    });

    // Ensure chat window is closed
    await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({ type: 'sessionChat/closeChatWindow' });
    });

    await page.waitForTimeout(300);

    // Simulate incoming message via WebSocket
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/addMessageFromWebSocket',
        payload: {
          id: 'msg-badge-test-1',
          senderId: 'other-user',
          senderName: 'Test User',
          message: 'Hello while closed',
          createdAt: new Date().toISOString(),
          channel
        }
      });
    }, sessionId);

    await page.waitForTimeout(500);

    // Badge should show "1"
    const badge = page.locator('div').filter({ hasText: /^1$/ }).first();
    await expect(badge).toBeVisible();
  });

  test('badge shows 99+ when count >= 100', async ({ page }) => {
    await page.waitForTimeout(1000);

    // Get session ID
    const sessionId = await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      return store.getState().sessionState?.sessionId || 'test-session-id';
    });

    // Ensure chat window is closed
    await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({ type: 'sessionChat/closeChatWindow' });
    });

    // Simulate 100 messages
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      for (let i = 0; i < 100; i++) {
        store.dispatch({
          type: 'sessionChat/addMessageFromWebSocket',
          payload: {
            id: `msg-bulk-${i}`,
            senderId: 'other-user',
            senderName: 'Test User',
            message: `Message ${i}`,
            createdAt: new Date().toISOString(),
            channel
          }
        });
      }
    }, sessionId);

    await page.waitForTimeout(500);

    // Badge should show "99+"
    const badge = page.locator('div').filter({ hasText: /^99\+$/ }).first();
    await expect(badge).toBeVisible();
  });

  test('badge resets when window opened', async ({ page }) => {
    await page.waitForTimeout(1000);

    // Get session ID
    const sessionId = await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      return store.getState().sessionState?.sessionId || 'test-session-id';
    });

    // Ensure chat window is closed
    await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({ type: 'sessionChat/closeChatWindow' });
    });

    // Simulate incoming message
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/addMessageFromWebSocket',
        payload: {
          id: 'msg-reset-test',
          senderId: 'other-user',
          senderName: 'Test User',
          message: 'Message before open',
          createdAt: new Date().toISOString(),
          channel
        }
      });
    }, sessionId);

    await page.waitForTimeout(500);

    // Verify badge shows "1"
    let badge = page.locator('div').filter({ hasText: /^1$/ }).first();
    await expect(badge).toBeVisible();

    // Open chat window via Redux dispatch (bypassing UI click)
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/setActiveChannel',
        payload: { channel, channelType: 'session' }
      });
      store.dispatch({ type: 'sessionChat/openChatWindow' });
    }, sessionId);

    await page.waitForTimeout(500);

    // Badge should be hidden (count reset to 0)
    badge = page.locator('div').filter({ hasText: /^\d+$/ }).first();
    await expect(badge).toBeHidden();
  });

  test('badge does not increment when viewing active channel', async ({ page }) => {
    await page.waitForTimeout(1000);

    // Get session ID
    const sessionId = await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      return store.getState().sessionState?.sessionId || 'test-session-id';
    });

    // Open chat window via Redux (bypassing UI)
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/setActiveChannel',
        payload: { channel, channelType: 'session' }
      });
      store.dispatch({ type: 'sessionChat/openChatWindow' });
    }, sessionId);

    await page.waitForTimeout(500);

    // Simulate incoming message while window is open and viewing same channel
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/addMessageFromWebSocket',
        payload: {
          id: 'msg-active-test',
          senderId: 'other-user',
          senderName: 'Test User',
          message: 'Message while viewing',
          createdAt: new Date().toISOString(),
          channel
        }
      });
    }, sessionId);

    await page.waitForTimeout(500);

    // Badge should still be hidden (count should remain 0)
    const badge = page.locator('div').filter({ hasText: /^\d+$/ }).first();
    await expect(badge).toBeHidden();
  });

  test('badge increments when viewing different channel', async ({ page }) => {
    await page.waitForTimeout(1000);

    // Get session ID
    const sessionId = await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      return store.getState().sessionState?.sessionId || 'test-session-id';
    });

    // Open chat window and set to session channel
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/setActiveChannel',
        payload: { channel, channelType: 'session' }
      });
      store.dispatch({ type: 'sessionChat/openChatWindow' });
    }, sessionId);

    await page.waitForTimeout(500);

    // Switch to a different channel
    await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/setActiveChannel',
        payload: {
          channel: 'different-channel',
          channelType: 'global'
        }
      });
    });

    await page.waitForTimeout(300);

    // Simulate incoming message to the original session channel
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/addMessageFromWebSocket',
        payload: {
          id: 'msg-different-channel-test',
          senderId: 'other-user',
          senderName: 'Test User',
          message: 'Message to different channel',
          createdAt: new Date().toISOString(),
          channel
        }
      });
    }, sessionId);

    await page.waitForTimeout(500);

    // Badge should show "1" (increment because viewing different channel)
    const badge = page.locator('div').filter({ hasText: /^1$/ }).first();
    await expect(badge).toBeVisible();
  });

  test('multiple messages increment badge correctly', async ({ page }) => {
    await page.waitForTimeout(1000);

    // Get session ID
    const sessionId = await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      return store.getState().sessionState?.sessionId || 'test-session-id';
    });

    // Ensure chat window is closed
    await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({ type: 'sessionChat/closeChatWindow' });
    });

    // Simulate 3 incoming messages
    for (let i = 1; i <= 3; i++) {
      await page.evaluate(({ channel, index }) => {
        const store = (window as any).__REDUX_STORE__;
        store.dispatch({
          type: 'sessionChat/addMessageFromWebSocket',
          payload: {
            id: `msg-multi-${index}`,
            senderId: 'other-user',
            senderName: 'Test User',
            message: `Message ${index}`,
            createdAt: new Date().toISOString(),
            channel
          }
        });
      }, { channel: sessionId, index: i });

      await page.waitForTimeout(200);
    }

    await page.waitForTimeout(500);

    // Badge should show "3"
    const badge = page.locator('div').filter({ hasText: /^3$/ }).first();
    await expect(badge).toBeVisible();
  });

  test('badge hidden after page reload without new messages', async ({ page }) => {
    await page.waitForTimeout(1000);

    // Get session ID
    const sessionId = await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      return store.getState().sessionState?.sessionId || 'test-session-id';
    });

    // Ensure chat window is closed
    await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({ type: 'sessionChat/closeChatWindow' });
    });

    // Add some messages to create unread count
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      for (let i = 0; i < 5; i++) {
        store.dispatch({
          type: 'sessionChat/addMessageFromWebSocket',
          payload: {
            id: `msg-persist-${i}`,
            senderId: 'other-user',
            senderName: 'Test User',
            message: `Persist message ${i}`,
            createdAt: new Date().toISOString(),
            channel
          }
        });
      }
    }, sessionId);

    await page.waitForTimeout(500);

    // Verify badge shows "5"
    let badge = page.locator('div').filter({ hasText: /^5$/ }).first();
    await expect(badge).toBeVisible();

    // Open and close window to mark as read and save lastReadAt
    await page.evaluate((channel) => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({
        type: 'sessionChat/setActiveChannel',
        payload: { channel, channelType: 'session' }
      });
      store.dispatch({ type: 'sessionChat/openChatWindow' });
    }, sessionId);

    await page.waitForTimeout(300);

    // Close window
    await page.evaluate(() => {
      const store = (window as any).__REDUX_STORE__;
      store.dispatch({ type: 'sessionChat/closeChatWindow' });
    });

    await page.waitForTimeout(300);

    // Reload the page
    await page.reload();
    await page.waitForLoadState('domcontentloaded');
    await page.waitForTimeout(2000);

    // Badge should be hidden (no new messages after reload, messages not persisted)
    badge = page.locator('div').filter({ hasText: /^\d+$/ }).first();
    await expect(badge).toBeHidden();

    // Verify lastReadAt persisted in localStorage
    const lastReadAt = await page.evaluate((channel) => {
      const stored = localStorage.getItem('jk_chat_lastReadAt');
      if (!stored) return null;
      const data = JSON.parse(stored);
      return data[channel];
    }, sessionId);

    expect(lastReadAt).toBeTruthy();
  });
});
