/**
 * NAV-001 V2 — sidebar context expansion-state tests.
 *
 * Covers: per-user localStorage hydration; explicit toggle persistence;
 * auto-expand-on-navigation does NOT persist; user-id change re-hydrates.
 */
import { act, render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import { SidebarProvider } from './sidebar-context';
import { useSidebar } from './use-sidebar';

const HUB_KEY_PREFIX = 'rankwiz.sidebar.expanded.';

function Probe() {
  const { expandedHubs, toggleHub, isHubExpanded, autoExpandHub } = useSidebar();
  return (
    <div>
      <span data-testid="expanded-set">{Array.from(expandedHubs).sort().join(',')}</span>
      <span data-testid="overview-expanded">{String(isHubExpanded('overview'))}</span>
      <button onClick={() => toggleHub('overview')}>toggle-overview</button>
      <button onClick={() => toggleHub('content')}>toggle-content</button>
      <button onClick={() => autoExpandHub('opportunities')}>auto-expand-opp</button>
    </div>
  );
}

describe('SidebarProvider — expandedHubs (NAV-001 V2)', () => {
  beforeEach(() => {
    localStorage.clear();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('starts with empty expanded set when no saved state for user', () => {
    render(
      <SidebarProvider userId={42}>
        <Probe />
      </SidebarProvider>,
    );
    expect(screen.getByTestId('expanded-set').textContent).toBe('');
    expect(screen.getByTestId('overview-expanded').textContent).toBe('false');
  });

  it('hydrates expanded set from localStorage on mount', () => {
    localStorage.setItem(`${HUB_KEY_PREFIX}42`, JSON.stringify(['overview', 'content']));
    render(
      <SidebarProvider userId={42}>
        <Probe />
      </SidebarProvider>,
    );
    expect(screen.getByTestId('expanded-set').textContent).toBe('content,overview');
    expect(screen.getByTestId('overview-expanded').textContent).toBe('true');
  });

  it('persists explicit toggleHub actions to localStorage under per-user key', async () => {
    const user = userEvent.setup();
    render(
      <SidebarProvider userId={42}>
        <Probe />
      </SidebarProvider>,
    );

    await user.click(screen.getByText('toggle-overview'));
    expect(screen.getByTestId('expanded-set').textContent).toBe('overview');

    const stored = localStorage.getItem(`${HUB_KEY_PREFIX}42`);
    expect(stored).not.toBeNull();
    const parsed = JSON.parse(stored as string);
    expect(parsed).toEqual(['overview']);

    // Toggling again removes it AND persists the empty state
    await user.click(screen.getByText('toggle-overview'));
    expect(screen.getByTestId('expanded-set').textContent).toBe('');
    const stored2 = localStorage.getItem(`${HUB_KEY_PREFIX}42`);
    expect(JSON.parse(stored2 as string)).toEqual([]);
  });

  it('does NOT persist auto-expand actions (transient nicety only)', async () => {
    const user = userEvent.setup();
    render(
      <SidebarProvider userId={42}>
        <Probe />
      </SidebarProvider>,
    );

    await user.click(screen.getByText('auto-expand-opp'));

    expect(screen.getByTestId('expanded-set').textContent).toBe('opportunities');
    // Critical contract: auto-expand never writes to storage
    expect(localStorage.getItem(`${HUB_KEY_PREFIX}42`)).toBeNull();
  });

  it('suppresses auto-expand once user has any saved state', () => {
    localStorage.setItem(`${HUB_KEY_PREFIX}42`, JSON.stringify([]));
    render(
      <SidebarProvider userId={42}>
        <Probe />
      </SidebarProvider>,
    );

    // Saved state exists (empty array) — auto-expansion must NOT add anything
    act(() => {
      screen.getByText('auto-expand-opp').click();
    });

    expect(screen.getByTestId('expanded-set').textContent).toBe('');
  });

  it('uses per-user key — different users get different state', () => {
    localStorage.setItem(`${HUB_KEY_PREFIX}1`, JSON.stringify(['overview']));
    localStorage.setItem(`${HUB_KEY_PREFIX}2`, JSON.stringify(['content']));

    const { rerender } = render(
      <SidebarProvider userId={1}>
        <Probe />
      </SidebarProvider>,
    );
    expect(screen.getByTestId('expanded-set').textContent).toBe('overview');

    rerender(
      <SidebarProvider userId={2}>
        <Probe />
      </SidebarProvider>,
    );
    expect(screen.getByTestId('expanded-set').textContent).toBe('content');
  });

  it('skips persistence silently when userId is null', async () => {
    const user = userEvent.setup();
    render(
      <SidebarProvider userId={null}>
        <Probe />
      </SidebarProvider>,
    );
    await user.click(screen.getByText('toggle-overview'));
    expect(screen.getByTestId('expanded-set').textContent).toBe('overview');
    // No localStorage entry for null user
    const keys = Object.keys(localStorage).filter((k) => k.startsWith(HUB_KEY_PREFIX));
    expect(keys).toEqual([]);
  });

  it('handles malformed stored JSON gracefully (resets to empty)', () => {
    localStorage.setItem(`${HUB_KEY_PREFIX}42`, '{not valid json');
    render(
      <SidebarProvider userId={42}>
        <Probe />
      </SidebarProvider>,
    );
    expect(screen.getByTestId('expanded-set').textContent).toBe('');
  });

  it('handles non-array stored JSON gracefully', () => {
    localStorage.setItem(`${HUB_KEY_PREFIX}42`, JSON.stringify({ overview: true }));
    render(
      <SidebarProvider userId={42}>
        <Probe />
      </SidebarProvider>,
    );
    expect(screen.getByTestId('expanded-set').textContent).toBe('');
  });
});
