import { atom } from 'jotai';

const STORAGE_KEY = 'settings';

export type ThemeId = 'light-theme' | 'dark-theme';

export interface Settings {
  themeId?: ThemeId;
  useSystemTheme: boolean;
  isMarkdown: boolean;
  twitterEmoji: boolean;
  pageZoom: number;
  hideActivity: boolean;

  isPeopleDrawer: boolean;
  memberSortFilterIndex: number;
  enterForNewline: boolean;
  hideMembershipEvents: boolean;
  hideNickAvatarEvents: boolean;
  mediaAutoLoad: boolean;
  urlPreview: boolean;

  isNotificationSounds: boolean;
  inviteSpamFilter: boolean;

  developerTools: boolean;

  migrationsApplied?: Record<string, boolean>;
}

const DAWN_MIGRATION_KEY = 'dawn-redesign-v1';
const P3C_CLEANUP_KEY = 'dawn-p3c-cleanup';
const SYSTEM_TIME_FORMAT_CLEANUP_KEY = 'system-time-format-cleanup';
const ORPHAN_SETTINGS_CLEANUP_KEY = 'dawn-orphan-settings-cleanup';

const defaultSettings: Settings = {
  themeId: undefined,
  useSystemTheme: true,
  isMarkdown: true,
  twitterEmoji: false,
  pageZoom: 100,
  hideActivity: false,

  isPeopleDrawer: true,
  memberSortFilterIndex: 0,
  enterForNewline: false,
  hideMembershipEvents: false,
  hideNickAvatarEvents: true,
  mediaAutoLoad: true,
  urlPreview: true,

  isNotificationSounds: true,
  inviteSpamFilter: true,

  developerTools: false,
};

export const setSettings = (settings: Settings) => {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
};

export const getSettings = (): Settings => {
  const raw = localStorage.getItem(STORAGE_KEY);

  let parsed: Partial<Settings> | null = null;
  if (raw !== null) {
    try {
      parsed = JSON.parse(raw) as Partial<Settings>;
    } catch {
      parsed = null;
    }
  }

  const merged: Settings = { ...defaultSettings, ...(parsed ?? {}) };

  // One-shot Dawn redesign migration: force the dark theme on existing users
  // so they see the redesigned palette on their first load post-migration.
  // Stamped so we run it exactly once. Brand-new users (no stored settings yet)
  // skip this branch entirely and keep the `useSystemTheme: true` default —
  // now that the Vojo light theme exists they should follow the OS preference
  // out of the box rather than being pinned to dark.
  if (raw !== null && !merged.migrationsApplied?.[DAWN_MIGRATION_KEY]) {
    merged.useSystemTheme = false;
    merged.themeId = 'dark-theme';
    merged.migrationsApplied = {
      ...(merged.migrationsApplied ?? {}),
      [DAWN_MIGRATION_KEY]: true,
    };
    setSettings(merged);
  }

  // P3c cleanup migration: strip orphan persisted fields removed by the
  // universal Stream collapse (`messageLayout`, `messageSpacing`,
  // `legacyUsernameColor`). Symmetric to the Dawn migration above — synchronous
  // sweep of stale keys at first load, stamped so it runs exactly once.
  if (!merged.migrationsApplied?.[P3C_CLEANUP_KEY]) {
    const orphan = merged as unknown as Record<string, unknown>;
    delete orphan.messageLayout;
    delete orphan.messageSpacing;
    delete orphan.legacyUsernameColor;
    merged.migrationsApplied = {
      ...(merged.migrationsApplied ?? {}),
      [P3C_CLEANUP_KEY]: true,
    };
    setSettings(merged);
  }

  // System time-format migration: drop the user-facing `hour24Clock` /
  // `dateFormatString` fields — both now derived from the runtime locale via
  // `Intl.DateTimeFormat` (see `utils/time.ts`). One-shot strip of the orphan
  // keys from existing users' persisted JSON.
  if (!merged.migrationsApplied?.[SYSTEM_TIME_FORMAT_CLEANUP_KEY]) {
    const orphan = merged as unknown as Record<string, unknown>;
    delete orphan.hour24Clock;
    delete orphan.dateFormatString;
    merged.migrationsApplied = {
      ...(merged.migrationsApplied ?? {}),
      [SYSTEM_TIME_FORMAT_CLEANUP_KEY]: true,
    };
    setSettings(merged);
  }

  // Dawn remnant sweep: strip the three orphan settings that had no UI toggle
  // and were frozen at their defaults forever — `editorToolbar` (only ever
  // pre-opened the edit overlay's toolbar), `encUrlPreview` (encrypted rooms now
  // never auto-preview, privacy-safe) and `showHiddenEvents` (the dev-only hidden
  // -event view, permanently off). One-shot strip of the stale persisted keys.
  if (!merged.migrationsApplied?.[ORPHAN_SETTINGS_CLEANUP_KEY]) {
    const orphan = merged as unknown as Record<string, unknown>;
    delete orphan.editorToolbar;
    delete orphan.encUrlPreview;
    delete orphan.showHiddenEvents;
    merged.migrationsApplied = {
      ...(merged.migrationsApplied ?? {}),
      [ORPHAN_SETTINGS_CLEANUP_KEY]: true,
    };
    setSettings(merged);
  }

  return merged;
};

const baseSettings = atom<Settings>(getSettings());
export const settingsAtom = atom<Settings, [Settings], undefined>(
  (get) => get(baseSettings),
  (get, set, update) => {
    set(baseSettings, update);
    setSettings(update);
  }
);
