// @vitest-environment jsdom
import { act, createElement } from 'react';
import { createRoot, type Root } from 'react-dom/client';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';

import { CHAT_SETTINGS_STORAGE_KEY } from '../types';
import { useChatSettings, type UseChatSettingsReturn } from '../useChatSettings';

(globalThis as Record<string, unknown>).IS_REACT_ACT_ENVIRONMENT = true;

let container: HTMLDivElement;
let root: Root;
let api: UseChatSettingsReturn | null = null;

function Probe() {
  api = useChatSettings();
  return null;
}

beforeEach(() => {
  window.localStorage.clear();
  container = document.createElement('div');
  document.body.appendChild(container);
  root = createRoot(container);
});

afterEach(() => {
  act(() => root.unmount());
  container.remove();
  window.localStorage.clear();
  api = null;
});

async function flush() {
  await act(async () => {
    await Promise.resolve();
  });
}

describe('useChatSettings', () => {
  it('exposes the default settings before anything is stored', async () => {
    await act(async () => root.render(createElement(Probe)));
    expect(api!.settings.pageContext.linked).toBe(false);
    expect(api!.settings.audio.muted).toBe(false);
    expect(api!.settings.dock.side).toBe('right');
  });

  it('updates only the targeted slice, leaving siblings untouched', async () => {
    await act(async () => root.render(createElement(Probe)));
    const audioBefore = api!.settings.audio;

    await act(async () => api!.updateDock({ side: 'left' }));

    expect(api!.settings.dock.side).toBe('left');
    // Audio slice identity is unchanged — a feature never touches another's.
    expect(api!.settings.audio).toBe(audioBefore);
  });

  it('setPageContextLinked persists the opt-in under the central key', async () => {
    await act(async () => root.render(createElement(Probe)));
    await act(async () => api!.setPageContextLinked(true));
    await flush();

    expect(api!.settings.pageContext.linked).toBe(true);
    const stored = JSON.parse(
      window.localStorage.getItem(CHAT_SETTINGS_STORAGE_KEY)!,
    );
    expect(stored.pageContext.linked).toBe(true);
  });

  it('reset restores every slice to defaults', async () => {
    await act(async () => root.render(createElement(Probe)));
    await act(async () => {
      api!.setAudioMuted(true);
      api!.updateDock({ side: 'left' });
    });
    await flush();
    expect(api!.settings.audio.muted).toBe(true);

    await act(async () => api!.reset());
    expect(api!.settings.audio.muted).toBe(false);
    expect(api!.settings.dock.side).toBe('right');
  });
});
