import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import {
  getScopedPreferenceCookieName,
  getScopedPreferenceKey,
  readCurrentUserScopedPreference,
  readScopedPreference,
  writeScopedPreference,
} from './preferences'

function installBrowser(cookie = '') {
  const store = new Map<string, string>()
  let cookieValue = cookie
  Object.defineProperty(globalThis, 'window', {
    configurable: true,
    value: {
      localStorage: {
        getItem: (key: string) => store.get(key) ?? null,
        setItem: (key: string, value: string) => store.set(key, value),
        removeItem: (key: string) => store.delete(key),
      },
    },
  })
  Object.defineProperty(globalThis, 'document', {
    configurable: true,
    value: {
      get cookie() {
        return cookieValue
      },
      set cookie(value: string) {
        const [pair] = value.split(';')
        const [name, val] = pair.split('=')
        const existing = cookieValue
          .split(';')
          .map((chunk) => chunk.trim())
          .filter(Boolean)
          .filter((chunk) => !chunk.startsWith(`${name}=`))
        existing.push(`${name}=${val}`)
        cookieValue = existing.join('; ')
      },
    },
  })
  Object.defineProperty(globalThis, 'atob', {
    configurable: true,
    value: (value: string) => Buffer.from(value, 'base64').toString('binary'),
  })
  return { store, get cookie() { return cookieValue } }
}

beforeEach(() => {
  installBrowser()
})

afterEach(() => {
  Reflect.deleteProperty(globalThis, 'window')
  Reflect.deleteProperty(globalThis, 'document')
  Reflect.deleteProperty(globalThis, 'atob')
})

describe('dashboard scoped preferences', () => {
  it('uses base keys when no employee token is available', () => {
    expect(getScopedPreferenceKey('theme')).toBe('theme')
    expect(getScopedPreferenceCookieName('theme')).toBe('theme')
  })

  it('prefers scoped cookie/current user values before local storage', () => {
    Reflect.deleteProperty(globalThis, 'window')
    Reflect.deleteProperty(globalThis, 'document')
    const browser = installBrowser('theme=dark')
    browser.store.set('theme', 'local-dark')

    expect(readCurrentUserScopedPreference('theme')).toBe('dark')
    expect(readScopedPreference('theme')).toBe('dark')
  })

  it('falls back through shared cookie, scoped local storage, base key, and legacy keys', () => {
    const browser = installBrowser('theme=dark')
    expect(readScopedPreference('theme', ['legacy-theme'])).toBe('dark')

    Reflect.deleteProperty(globalThis, 'window')
    Reflect.deleteProperty(globalThis, 'document')
    const second = installBrowser()
    second.store.set('theme', 'base')
    second.store.set('legacy-theme', 'legacy')
    expect(readScopedPreference('theme', ['legacy-theme'])).toBe('base')
  })

  it('writes shared and legacy preference values without auth-token scoping', () => {
    const browser = installBrowser()

    writeScopedPreference('language', 'fr', ['old-language'])

    expect(browser.store.get('language')).toBe('fr')
    expect(browser.store.get('old-language')).toBe('fr')
    expect(browser.cookie).toContain('language=fr')
  })
})
