/**
 * Quick Settings — Web-only user preferences for AI pipeline and map behavior.
 * Desktop (Tauri) manages AI config via its own settings window.
 *
 * TODO: Migrate panel visibility, sources, and language selector into this
 *       settings hub once the UI is extended with additional sections.
 */

import { isDesktopRuntime } from './runtime';

const STORAGE_KEY_BROWSER_MODEL = 'wm-ai-flow-browser-model';
const STORAGE_KEY_CLOUD_LLM = 'wm-ai-flow-cloud-llm';
const STORAGE_KEY_MAP_NEWS_FLASH = 'wm-map-news-flash';
const STORAGE_KEY_HEADLINE_MEMORY = 'wm-headline-memory';
const STORAGE_KEY_BADGE_ANIMATION = 'wm-badge-animation';
const STORAGE_KEY_STREAM_QUALITY = 'wm-stream-quality';
const EVENT_NAME = 'ai-flow-changed';
const STREAM_QUALITY_EVENT = 'stream-quality-changed';

export interface AiFlowSettings {
  browserModel: boolean;
  cloudLlm: boolean;
  mapNewsFlash: boolean;
  headlineMemory: boolean;
  badgeAnimation: boolean;
}

function readBool(key: string, defaultValue: boolean): boolean {
  try {
    const raw = localStorage.getItem(key);
    if (raw === null) return defaultValue;
    return raw === 'true';
  } catch {
    return defaultValue;
  }
}

function writeBool(key: string, value: boolean): void {
  try {
    localStorage.setItem(key, String(value));
  } catch {
    // Quota or private-browsing; silently ignore
  }
}

const STORAGE_KEY_MAP: Record<keyof AiFlowSettings, string> = {
  browserModel: STORAGE_KEY_BROWSER_MODEL,
  cloudLlm: STORAGE_KEY_CLOUD_LLM,
  mapNewsFlash: STORAGE_KEY_MAP_NEWS_FLASH,
  headlineMemory: STORAGE_KEY_HEADLINE_MEMORY,
  badgeAnimation: STORAGE_KEY_BADGE_ANIMATION,
};

const DEFAULTS: AiFlowSettings = {
  browserModel: false,
  cloudLlm: true,
  mapNewsFlash: true,
  headlineMemory: false,
  badgeAnimation: false,
};

export function getAiFlowSettings(): AiFlowSettings {
  return {
    browserModel: readBool(STORAGE_KEY_BROWSER_MODEL, DEFAULTS.browserModel),
    cloudLlm: readBool(STORAGE_KEY_CLOUD_LLM, DEFAULTS.cloudLlm),
    mapNewsFlash: readBool(STORAGE_KEY_MAP_NEWS_FLASH, DEFAULTS.mapNewsFlash),
    headlineMemory: readBool(STORAGE_KEY_HEADLINE_MEMORY, DEFAULTS.headlineMemory),
    badgeAnimation: readBool(STORAGE_KEY_BADGE_ANIMATION, DEFAULTS.badgeAnimation),
  };
}

/**
 * Effective Headline Memory state. Headline Memory implementation requires
 * a local embeddings model in the ML worker, so on web it can only function
 * when the Browser Local Model parent toggle is also enabled — otherwise
 * we'd silently download/run an ML model the user opted out of via the
 * parent toggle. The persisted value is preserved (the settings UI reads
 * `getAiFlowSettings().headlineMemory` for the raw value) so re-enabling
 * Browser Local Model restores the user's prior Headline Memory choice.
 *
 * The Browser Local Model toggle is web-only — `preferences-content.ts`
 * skips rendering it on desktop, and `App.ts` initializes the ML worker
 * unconditionally on desktop. So the parent gate must be skipped on
 * desktop, otherwise Headline Memory would be silently dead on every
 * desktop install (the hidden web key never flips to true).
 */
export function isHeadlineMemoryEnabled(): boolean {
  const headline = readBool(STORAGE_KEY_HEADLINE_MEMORY, DEFAULTS.headlineMemory);
  if (!headline) return false;
  if (isDesktopRuntime()) return true;
  const browser = readBool(STORAGE_KEY_BROWSER_MODEL, DEFAULTS.browserModel);
  return browser;
}

export function setAiFlowSetting(key: keyof AiFlowSettings, value: boolean): void {
  writeBool(STORAGE_KEY_MAP[key], value);
  window.dispatchEvent(new CustomEvent(EVENT_NAME, { detail: { key } }));
}

export function isAnyAiProviderEnabled(): boolean {
  const s = getAiFlowSettings();
  return s.cloudLlm || s.browserModel;
}

export function subscribeAiFlowChange(cb: (changedKey?: keyof AiFlowSettings) => void): () => void {
  const handler = (e: Event) => {
    const detail = (e as CustomEvent).detail as { key?: keyof AiFlowSettings } | undefined;
    cb(detail?.key);
  };
  window.addEventListener(EVENT_NAME, handler);
  return () => window.removeEventListener(EVENT_NAME, handler);
}

// ── Stream Quality ──

export type StreamQuality = 'auto' | 'small' | 'medium' | 'large' | 'hd720';

export const STREAM_QUALITY_OPTIONS: { value: StreamQuality; label: string }[] = [
  { value: 'auto', label: 'Auto' },
  { value: 'small', label: 'Low (360p)' },
  { value: 'medium', label: 'Medium (480p)' },
  { value: 'large', label: 'High (480p+)' },
  { value: 'hd720', label: 'HD (720p)' },
];

export function getStreamQuality(): StreamQuality {
  try {
    const raw = localStorage.getItem(STORAGE_KEY_STREAM_QUALITY);
    if (raw && ['auto', 'small', 'medium', 'large', 'hd720'].includes(raw)) return raw as StreamQuality;
  } catch { /* ignore */ }
  return 'auto';
}

export function setStreamQuality(quality: StreamQuality): void {
  try {
    localStorage.setItem(STORAGE_KEY_STREAM_QUALITY, quality);
  } catch { /* ignore */ }
  window.dispatchEvent(new CustomEvent(STREAM_QUALITY_EVENT, { detail: { quality } }));
}

export function subscribeStreamQualityChange(cb: (quality: StreamQuality) => void): () => void {
  const handler = (e: Event) => {
    const detail = (e as CustomEvent).detail as { quality: StreamQuality };
    cb(detail.quality);
  };
  window.addEventListener(STREAM_QUALITY_EVENT, handler);
  return () => window.removeEventListener(STREAM_QUALITY_EVENT, handler);
}
