import * as storage from '$lib/util/safeLocalStorage';

const STORAGE_KEY = 'minstrel:theme';

export type ThemePreference = 'dark' | 'light' | 'system';
export type ResolvedTheme = 'dark' | 'light';

function readPref(): ThemePreference {
  const v = storage.read(STORAGE_KEY);
  return v === 'dark' || v === 'light' || v === 'system' ? v : 'system';
}

function systemResolved(): ResolvedTheme {
  if (typeof window === 'undefined' || !window.matchMedia) return 'dark';
  return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
}

function resolve(pref: ThemePreference): ResolvedTheme {
  return pref === 'system' ? systemResolved() : pref;
}

function applyToDOM(resolved: ResolvedTheme): void {
  if (typeof document === 'undefined') return;
  document.documentElement.setAttribute('data-theme', resolved);
}

let _theme = $state<ThemePreference>(readPref());
// svelte-ignore state_referenced_locally
// Module-scope state with manual sync — _theme is read once at module
// init to seed _resolved; subsequent updates flow through setTheme()
// (which writes both) and the matchMedia listener (which writes
// _resolved when prefers-color-scheme flips). Not a missed-reactivity
// case; $derived doesn't apply at module scope here.
let _resolved = $state<ResolvedTheme>(resolve(_theme));

export const theme = {
  get value(): ThemePreference {
    return _theme;
  }
};

export const resolvedTheme = {
  get value(): ResolvedTheme {
    return _resolved;
  }
};

export function setTheme(pref: ThemePreference): void {
  _theme = pref;
  _resolved = resolve(pref);
  storage.write(STORAGE_KEY, pref);
  applyToDOM(_resolved);
}

if (typeof window !== 'undefined' && window.matchMedia) {
  const mq = window.matchMedia('(prefers-color-scheme: light)');
  mq.addEventListener('change', () => {
    if (_theme === 'system') {
      _resolved = systemResolved();
      applyToDOM(_resolved);
    }
  });
}
