import { describe, expect, it } from 'vitest';
import {
  SCREEN_IDS,
  WIRED_SCREENS,
  resolveShell,
  resolveScreen,
  findUnwiredOverrides,
  type ModTheme,
  type ThemeComponent,
} from './theme-contract.js';

// Sentinels — the resolver is opaque over components; a type-only ThemeComponent
// lets us cast plain objects without importing the astro runtime.
const SHELL = { __id: 'shell' } as unknown as ThemeComponent;
const HOST_DEFAULT = { __id: 'host-default' } as unknown as ThemeComponent;
const OVERRIDE = { __id: 'override' } as unknown as ThemeComponent;

const themeWithPostOverride: ModTheme = {
  id: 'editorial',
  name: 'Editorial',
  Shell: SHELL,
  overrides: { post: OVERRIDE },
};
const themeNoOverrides: ModTheme = { id: 'default', name: 'Default', Shell: SHELL, overrides: {} };

describe('SCREEN_IDS', () => {
  it('lists all eight public content screens', () => {
    expect([...SCREEN_IDS].sort()).toEqual(
      ['blueprint', 'contact', 'index', 'module', 'not-found', 'post', 'privacy', 'search'].sort(),
    );
  });
});

describe('WIRED_SCREENS', () => {
  it('contains exactly post, index, search, not-found', () => {
    expect([...WIRED_SCREENS].sort()).toEqual(['index', 'not-found', 'post', 'search']);
  });
});

describe('resolveShell', () => {
  it('always returns the active theme shell', () => {
    expect(resolveShell(themeWithPostOverride)).toBe(SHELL);
  });
});

describe('resolveScreen', () => {
  it('returns the override when the theme overrides that screen', () => {
    expect(resolveScreen(themeWithPostOverride, 'post', HOST_DEFAULT)).toBe(OVERRIDE);
  });
  it('falls back to the host default when the screen is not overridden', () => {
    expect(resolveScreen(themeWithPostOverride, 'index', HOST_DEFAULT)).toBe(HOST_DEFAULT);
    expect(resolveScreen(themeNoOverrides, 'post', HOST_DEFAULT)).toBe(HOST_DEFAULT);
  });
});

describe('findUnwiredOverrides', () => {
  it('returns [] when every override is on a wired screen', () => {
    expect(WIRED_SCREENS.has('post')).toBe(true);
    expect(findUnwiredOverrides(themeWithPostOverride)).toEqual([]);
  });
  it('returns the screens whose override is not yet wired (silent no-op guard)', () => {
    const lying: ModTheme = { id: 'x', name: 'X', Shell: SHELL, overrides: { blueprint: OVERRIDE } };
    expect(findUnwiredOverrides(lying)).toEqual(['blueprint']);
  });
  it('returns only the unwired screens from a mix of wired + unwired overrides', () => {
    const mixed: ModTheme = { id: 'x', name: 'X', Shell: SHELL, overrides: { post: OVERRIDE, index: OVERRIDE, contact: OVERRIDE } };
    expect(findUnwiredOverrides(mixed).sort()).toEqual(['contact']);
  });
});
