// @vitest-environment happy-dom
//
// Layout engine: the panel allow-list per workspace page, and the storage
// contract. All legacy-key migration was deleted for Beta 1 (treated as the
// first version ever), so loading must ignore anything that isn't the
// current key. (Scoped to happy-dom for localStorage, same as
// data/serverPins.test.js — the default vitest environment is node.)
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import {
  WORKSPACE_PANELS,
  createInitialLayout,
  loadWorkspaceLayouts,
  saveWorkspaceLayouts,
  validateLayout,
  workspaceBlocked,
} from './layoutEngine';

beforeEach(() => localStorage.clear());
afterEach(() => localStorage.clear());

describe('WORKSPACE_PANELS', () => {
  it('offers Device Management on the Revision Control page, before Console', () => {
    expect(WORKSPACE_PANELS.revision).toEqual(['repo', 'history', 'devices', 'console']);
  });
});

describe('validateLayout', () => {
  it('keeps a devices leaf in a revision layout', () => {
    const layout = {
      type: 'split',
      direction: 'vertical',
      ratio: 0.5,
      first: { type: 'leaf', panelId: 'repo' },
      second: { type: 'leaf', panelId: 'devices' },
    };
    expect(validateLayout(layout, 'revision')).toEqual(layout);
  });

  it('still drops a panel that page does not offer', () => {
    const layout = {
      type: 'split',
      direction: 'vertical',
      ratio: 0.5,
      first: { type: 'leaf', panelId: 'repo' },
      second: { type: 'leaf', panelId: 'server' },
    };
    expect(validateLayout(layout, 'revision')).toEqual({ type: 'leaf', panelId: 'repo' });
  });
});

describe('loadWorkspaceLayouts', () => {
  it('round-trips through the cbm- key', () => {
    const layouts = { revision: createInitialLayout('revision') };
    saveWorkspaceLayouts(layouts);
    expect(localStorage.getItem('cbm-layout-v1')).toBeTruthy();
    expect(loadWorkspaceLayouts()).toEqual(layouts);
  });

  it('returns defaults for an empty store', () => {
    expect(loadWorkspaceLayouts()).toEqual({
      revision: createInitialLayout('revision'),
      organization: createInitialLayout('organization'),
    });
  });

  it('ignores a stale rc-era key instead of migrating it', () => {
    localStorage.setItem('rc-layout-v12', JSON.stringify({ revision: { type: 'leaf', panelId: 'console' } }));
    localStorage.setItem('rc-layout-v8', JSON.stringify({ type: 'leaf', panelId: 'console' }));
    expect(loadWorkspaceLayouts()).toEqual({
      revision: createInitialLayout('revision'),
      organization: createInitialLayout('organization'),
    });
  });
});

describe('workspaceBlocked', () => {
  const loggedOut = { loggedIn: false, projectReady: false };
  const noProject = { loggedIn: true, projectReady: false };
  const working = { loggedIn: true, projectReady: true };

  it('blocks every server-backed page while logged out', () => {
    expect(workspaceBlocked('revision', loggedOut)).toBe(true);
    expect(workspaceBlocked('organization', loggedOut)).toBe(true);
    expect(workspaceBlocked('administration', loggedOut)).toBe(true);
  });

  it('never blocks Time Tracking, which runs offline', () => {
    expect(workspaceBlocked('time', loggedOut)).toBe(false);
    expect(workspaceBlocked('time', working)).toBe(false);
  });

  it('lets the server-scoped pages through on a session with no project', () => {
    // The bootstrap case: creating the very first project lives inside
    // Administration, so it cannot itself require a project to exist.
    expect(workspaceBlocked('administration', noProject)).toBe(false);
    expect(workspaceBlocked('organization', noProject)).toBe(false);
  });

  it('still blocks Revision Control until a project is active', () => {
    expect(workspaceBlocked('revision', noProject)).toBe(true);
    expect(workspaceBlocked('revision', working)).toBe(false);
  });

  it('treats an unknown workspace as project-scoped', () => {
    expect(workspaceBlocked('nonesuch', noProject)).toBe(true);
    expect(workspaceBlocked('nonesuch', working)).toBe(false);
  });
});
