/**
 * @vitest-environment happy-dom
 */
import { render } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { initialState as initialChatState } from '@/store/chat/initialState';
import { PortalViewType } from '@/store/chat/slices/portal/initialState';
import { useChatStore } from '@/store/chat/store';

import AgentIdSync from './AgentIdSync';

const useParamsMock = vi.hoisted(() => vi.fn());
const useSearchParamsMock = vi.hoisted(() => vi.fn());
const useNavigateMock = vi.hoisted(() => vi.fn());
const useLocationMock = vi.hoisted(() => vi.fn());

vi.mock('react-router', async () => {
  // eslint-disable-next-line @typescript-eslint/consistent-type-imports
  const actual = (await vi.importActual('react-router')) as typeof import('react-router');

  return {
    ...actual,
    useLocation: useLocationMock,
    useNavigate: () => useNavigateMock,
    useParams: useParamsMock,
    useSearchParams: useSearchParamsMock,
  };
});

describe('AgentIdSync', () => {
  beforeEach(() => {
    useParamsMock.mockReset();
    useSearchParamsMock.mockReset();
    useNavigateMock.mockReset();
    useLocationMock.mockReset();
    useLocationMock.mockReturnValue({ pathname: '/agent/agent-1' });

    useChatStore.setState(
      {
        ...initialChatState,
        activeAgentId: 'agent-1',
        activeTopicId: 'topic-1',
        portalStack: [{ type: PortalViewType.Home }],
        showPortal: true,
      },
      false,
    );
  });

  it('clears portal state when switching to another agent without a topic in the URL', () => {
    useParamsMock.mockReturnValue({ aid: 'agent-1' });
    useSearchParamsMock.mockReturnValue([new URLSearchParams(''), vi.fn()]);

    const { rerender } = render(<AgentIdSync />);

    expect(useChatStore.getState().showPortal).toBe(true);

    useParamsMock.mockReturnValue({ aid: 'agent-2' });
    useLocationMock.mockReturnValue({ pathname: '/agent/agent-2' });
    rerender(<AgentIdSync />);

    expect(useChatStore.getState().activeTopicId).toBeNull();
    expect(useChatStore.getState().portalStack).toEqual([]);
    expect(useChatStore.getState().showPortal).toBe(false);
  });

  it('still clears portal state when the destination URL already has a topic', () => {
    useParamsMock.mockReturnValue({ aid: 'agent-1' });
    useSearchParamsMock.mockReturnValue([new URLSearchParams('topic=topic-2'), vi.fn()]);

    const { rerender } = render(<AgentIdSync />);

    useParamsMock.mockReturnValue({ aid: 'agent-2' });
    useLocationMock.mockReturnValue({ pathname: '/agent/agent-2' });
    rerender(<AgentIdSync />);

    expect(useChatStore.getState().portalStack).toEqual([]);
    expect(useChatStore.getState().showPortal).toBe(false);
    expect(useChatStore.getState().activeTopicId).toBe('topic-1');
  });

  it('preserves the active topic when the destination route carries a topic path segment', () => {
    useParamsMock.mockReturnValue({ aid: 'agent-1', topicId: 'topic-1' });
    useSearchParamsMock.mockReturnValue([new URLSearchParams(''), vi.fn()]);

    const { rerender } = render(<AgentIdSync />);

    useParamsMock.mockReturnValue({ aid: 'agent-2', topicId: 'topic-2' });
    rerender(<AgentIdSync />);

    expect(useChatStore.getState().portalStack).toEqual([]);
    expect(useChatStore.getState().showPortal).toBe(false);
    expect(useChatStore.getState().activeTopicId).toBe('topic-1');
  });
});
