import { create } from 'zustand'
import { DEFAULT_SETTINGS, type Settings } from '@shared/ipc'
import { isPreview as PREVIEW } from '../isPreview'
import { logError } from '../reportError'

// The pre-load fallback is the canonical DEFAULT_SETTINGS (single-sourced from the
// shared contract, C1) — including theme:'system' (SR1) so there's no white-on-
// first-paint flash for a dark-mode user before the real settings arrive. In the
// browser preview a couple of fields differ: placeholder folder paths, and
// onboarding pre-dismissed so design work isn't blocked behind the welcome screen
// (a real first launch keeps DEFAULT_SETTINGS' false from main).
const FALLBACK: Settings = PREVIEW
  ? {
      ...DEFAULT_SETTINGS,
      videoFolder: 'C:\\Users\\you\\Documents\\Video',
      audioFolder: 'C:\\Users\\you\\Documents\\Audio',
      hasCompletedOnboarding: true
    }
  : DEFAULT_SETTINGS

interface SettingsState extends Settings {
  /** true once persisted settings have loaded (always true in preview) */
  loaded: boolean
  update: (partial: Partial<Settings>) => void
  /** re-fetch persisted settings from main (a backup restore changes them underneath) */
  reload: () => void
  /** open the OS folder picker and store the result as the video or audio folder */
  chooseFolder: (target: 'videoFolder' | 'audioFolder') => void
  /** clear a per-kind folder override, restoring its Documents\… default */
  clearFolder: (target: 'videoFolder' | 'audioFolder') => void
  /** open the Windows High Contrast settings page (AppearanceCard) */
  openHighContrastSettings: () => void
}

export const useSettings = create<SettingsState>((set, get) => ({
  ...FALLBACK,
  loaded: PREVIEW,

  update: (partial) => {
    set(partial) // optimistic local update
    if (PREVIEW) return
    // M34: reconcile with main's authoritative, validated result — for exactly the
    // keys we changed — so a value main clamps, sanitizes, or rejects (e.g. an
    // unsafe filenameTemplate, an out-of-range maxConcurrent, a malformed
    // rateLimit) stops showing as accepted in the UI until restart.
    window.api
      .setSettings(partial)
      .then((saved) => {
        const reconciled = Object.fromEntries(
          (Object.keys(partial) as (keyof Settings)[]).map((k) => [k, saved[k]])
        ) as Partial<Settings>
        set(reconciled)
      })
      .catch(logError('setSettings'))
  },

  reload: () => {
    if (PREVIEW) return
    window.api
      .getSettings()
      .then((s) => set({ ...s, loaded: true }))
      .catch(logError('getSettings'))
  },

  chooseFolder: (target) => {
    if (PREVIEW) return
    // Seed the OS picker with the folder this target currently points at (W5).
    window.api
      .chooseFolder(get()[target])
      .then((dir) => {
        if (dir) get().update({ [target]: dir })
      })
      .catch(logError('chooseFolder'))
  },

  clearFolder: (target) => get().update({ [target]: '' }),

  openHighContrastSettings: () => {
    if (!PREVIEW) window.api.openHighContrastSettings().catch(logError('openHighContrastSettings'))
  }
}))

// Load persisted settings on startup.
if (!PREVIEW) useSettings.getState().reload()
