// @vitest-environment happy-dom
//
// What AppShell presents on boot: the Login modal, not the logged-out
// placeholder — the placeholder is only what's left behind once that modal is
// dismissed — and nothing at all while a remembered connection is being
// resumed. No react-testing-library in this repo (see FileTree.statuses.test.jsx);
// mount with react-dom/client directly.
//
// Everything below AppShell is stubbed: the chrome, the layout tree and the
// modal stack all have suites of their own, and the real ones drag in the
// Tauri bridge. What's under test here is only the boot-time decision.
import { act } from 'react';
import { createRoot } from 'react-dom/client';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const state = vi.hoisted(() => ({ connection: null }));

vi.mock('./platform', () => ({
  isTauri: false,
  isMac: false,
  isWindows: false,
  isLinux: true,
}));
vi.mock('./components/MenuBar', () => ({ MenuBar: () => null }));
vi.mock('./components/LayoutRoot', () => ({
  LayoutRoot: () => <div data-role="layout" />,
}));
vi.mock('./components/Panel', () => ({ DragGhost: () => null }));
vi.mock('./components/modals/DeviceLimitModal', () => ({ DeviceLimitModal: () => null }));
vi.mock('./components/modals/AppModals', () => ({
  AppModals: ({ activeModal, onClose }) =>
    activeModal ? (
      <div data-role="modal" data-modal={activeModal}>
        <button type="button" data-role="modal-close" onClick={onClose}>
          Close
        </button>
      </div>
    ) : null,
}));
vi.mock('./layout/useLayoutTree', () => ({
  useLayoutTree: () => ({
    activeWorkspace: 'revision',
    setActiveWorkspace: vi.fn(),
    layout: { type: 'leaf', panel: 'repo' },
    visibility: {},
    dragState: null,
    toggleVisible: vi.fn(),
    resetWindows: vi.fn(),
    resizeSplit: vi.fn(),
    startDrag: vi.fn(),
    updateDragZone: vi.fn(),
    endDrag: vi.fn(),
  }),
}));
vi.mock('./context/ConnectionContext', () => ({
  ConnectionProvider: ({ children }) => children,
  useConnection: () => state.connection,
}));
vi.mock('./context/SettingsContext', () => ({
  SettingsProvider: ({ children }) => children,
  useSettings: () => ({ showTimeTracking: false }),
}));
vi.mock('./context/ServerDataContext', () => ({
  ServerDataProvider: ({ children }) => children,
}));
vi.mock('./context/ConsoleContext', () => ({ ConsoleProvider: ({ children }) => children }));
vi.mock('./context/FileTreeTabContext', () => ({
  FileTreeTabProvider: ({ children }) => children,
}));

import App from './App';

let container;
let root;

function connection(overrides) {
  return {
    projectReady: false,
    loggedIn: false,
    account: null,
    loginSeq: 0,
    organizationEnabled: false,
    startupPending: false,
    workspacePath: '',
    ...overrides,
  };
}

function render() {
  act(() => {
    root.render(<App />);
  });
}

const modal = () => container.querySelector('[data-role="modal"]');
const placeholder = () => container.querySelector('.workspace-empty--disconnected');

beforeEach(() => {
  container = document.createElement('div');
  document.body.appendChild(container);
  root = createRoot(container);
  state.connection = connection();
});

afterEach(() => {
  act(() => root.unmount());
  container.remove();
  container = null;
});

describe('startup presentation', () => {
  it('opens on the login modal rather than the logged-out placeholder', () => {
    render();

    expect(modal()?.dataset.modal).toBe('connections');
    expect(placeholder()).toBeNull();
  });

  it('shows the placeholder only once that modal is closed', () => {
    render();

    act(() => {
      container.querySelector('[data-role="modal-close"]').click();
    });

    expect(modal()).toBeNull();
    expect(placeholder()).not.toBeNull();
  });

  it('holds off while a remembered connection is being resumed', () => {
    state.connection = connection({ startupPending: true });
    render();

    // No form flashed at someone who is about to be signed in, and no empty
    // window either.
    expect(modal()).toBeNull();
    expect(placeholder()).toBeNull();
    expect(container.querySelector('[aria-label="Signing in"]')).not.toBeNull();
  });

  it('drops a resumed session straight into its workspace, never showing the modal', () => {
    state.connection = connection({ startupPending: true });
    render();

    state.connection = connection({ loggedIn: true, projectReady: true, workspacePath: '/w' });
    render();

    expect(modal()).toBeNull();
    expect(container.querySelector('[data-role="layout"]')).not.toBeNull();
  });

  it('opens the modal for a resumed session with no workspace folder set', () => {
    // Same as a typed login with nowhere to go: the modal stays up on its
    // Projects page so a folder can be picked.
    state.connection = connection({ startupPending: true });
    render();

    state.connection = connection({ loggedIn: true, projectReady: true, workspacePath: '' });
    render();

    expect(modal()?.dataset.modal).toBe('connections');
  });

  it('does not re-open the modal when a later logout drops the session', () => {
    render();
    act(() => {
      container.querySelector('[data-role="modal-close"]').click();
    });
    expect(modal()).toBeNull();

    // Log in, then out again — the boot-time decision is made once, so this
    // must not trap the user behind a modal they already dismissed.
    state.connection = connection({ loggedIn: true, projectReady: true, workspacePath: '/w' });
    render();
    state.connection = connection();
    render();

    expect(modal()).toBeNull();
    expect(placeholder()).not.toBeNull();
  });
});
