import { PATTERNS, type BackgroundPatternId } from '$lib/desktop-patterns'

export interface BackgroundConfig {
  pattern: BackgroundPatternId
  color: string // pattern foreground color, hex
  fillColor: string | null // fill behind the pattern (its "gaps"); null = transparent, i.e. the app's own theme background shows through
  opacity: number // 0..1
  fade: number // 0..1 — 0 disables the vignette mask entirely
  scale: number // pattern tile-size multiplier; 1 = natural size
  rotation: number // degrees, 0..359
}

const STORAGE_KEY = 'oikos-desktop-bg'
const VALID_IDS = new Set(PATTERNS.map((p) => p.id))

// Matches the previous hardcoded desktop background (bubbles, brand blue,
// tuned low so it reads as texture rather than noise) so this feature ships
// as "now configurable" rather than a visual regression on first load.
const DEFAULTS: BackgroundConfig = {
  pattern: 'bubbles',
  color: '#444cf7',
  fillColor: null,
  opacity: 0.08,
  fade: 0,
  scale: 1,
  rotation: 0
}

function clamp01(v: unknown, fallback: number): number {
  const n = typeof v === 'number' ? v : Number(v)
  if (!Number.isFinite(n)) return fallback
  return Math.min(1, Math.max(0, n))
}

function clampScale(v: unknown): number {
  const n = typeof v === 'number' ? v : Number(v)
  if (!Number.isFinite(n)) return DEFAULTS.scale
  return Math.min(3, Math.max(0.4, n))
}

function clampRotation(v: unknown): number {
  const n = typeof v === 'number' ? v : Number(v)
  if (!Number.isFinite(n)) return DEFAULTS.rotation
  return ((n % 360) + 360) % 360
}

function isHexColor(c: unknown): c is string {
  return typeof c === 'string' && /^#[0-9a-fA-F]{6}$/.test(c)
}

function storedConfig(): BackgroundConfig {
  if (typeof localStorage === 'undefined') return DEFAULTS
  const raw = localStorage.getItem(STORAGE_KEY)
  if (!raw) return DEFAULTS
  try {
    const parsed = JSON.parse(raw)
    return {
      pattern: VALID_IDS.has(parsed.pattern) ? parsed.pattern : DEFAULTS.pattern,
      color: isHexColor(parsed.color) ? parsed.color : DEFAULTS.color,
      fillColor:
        parsed.fillColor === null
          ? null
          : isHexColor(parsed.fillColor)
            ? parsed.fillColor
            : DEFAULTS.fillColor,
      opacity: clamp01(parsed.opacity, DEFAULTS.opacity),
      fade: clamp01(parsed.fade, DEFAULTS.fade),
      scale: clampScale(parsed.scale),
      rotation: clampRotation(parsed.rotation)
    }
  } catch {
    return DEFAULTS
  }
}

let config: BackgroundConfig = $state(storedConfig())

function persist(): void {
  if (typeof localStorage !== 'undefined') localStorage.setItem(STORAGE_KEY, JSON.stringify(config))
}

export function getBackground(): BackgroundConfig {
  return config
}

export function setBackgroundPattern(pattern: BackgroundPatternId): void {
  config = { ...config, pattern }
  persist()
}

export function setPatternColor(color: string): void {
  if (!isHexColor(color)) return
  config = { ...config, color }
  persist()
}

// null clears back to "auto" (transparent — the app's theme background
// shows through the pattern's gaps).
export function setFillColor(color: string | null): void {
  if (color !== null && !isHexColor(color)) return
  config = { ...config, fillColor: color }
  persist()
}

export function setBackgroundOpacity(opacity: number): void {
  config = { ...config, opacity: clamp01(opacity, DEFAULTS.opacity) }
  persist()
}

export function setBackgroundFade(fade: number): void {
  config = { ...config, fade: clamp01(fade, DEFAULTS.fade) }
  persist()
}

export function setBackgroundScale(scale: number): void {
  config = { ...config, scale: clampScale(scale) }
  persist()
}

export function setBackgroundRotation(rotation: number): void {
  config = { ...config, rotation: clampRotation(rotation) }
  persist()
}
