import { create } from 'zustand'

export const ACCESS_TOKEN = 'study_work_access_token'
export const AUTH_USER = 'study_work_auth_user'

export interface AuthUser {
  id: string
  name: string
  username: string
  email: string
  role?: string
  roleName?: string
  mustChangePassword?: boolean
  avatar?: string
  permissions?: Record<string, string[]>
}

interface AuthState {
  auth: {
    user: AuthUser | null
    setUser: (user: AuthUser | null) => void
    accessToken: string
    setAccessToken: (accessToken: string) => void
    resetAccessToken: () => void
    reset: () => void
  }
}

function readStorage<T>(key: string, fallback: T): T {
  if (typeof window === 'undefined') {
    return fallback
  }

  const value = window.localStorage.getItem(key)
  if (!value) {
    return fallback
  }

  try {
    return JSON.parse(value) as T
  } catch {
    window.localStorage.removeItem(key)
    return fallback
  }
}

function writeStorage(key: string, value: unknown) {
  if (typeof window === 'undefined') {
    return
  }

  window.localStorage.setItem(key, JSON.stringify(value))
}

function removeStorage(key: string) {
  if (typeof window === 'undefined') {
    return
  }

  window.localStorage.removeItem(key)
}

export const useAuthStore = create<AuthState>()((set) => {
  const initToken = readStorage(ACCESS_TOKEN, '')
  const initUser = readStorage<AuthUser | null>(AUTH_USER, null)

  return {
    auth: {
      user: initUser,
      setUser: (user) =>
        set((state) => {
          if (user) {
            writeStorage(AUTH_USER, user)
          } else {
            removeStorage(AUTH_USER)
          }
          return { ...state, auth: { ...state.auth, user } }
        }),
      accessToken: initToken,
      setAccessToken: (accessToken) =>
        set((state) => {
          writeStorage(ACCESS_TOKEN, accessToken)
          return { ...state, auth: { ...state.auth, accessToken } }
        }),
      resetAccessToken: () =>
        set((state) => {
          removeStorage(ACCESS_TOKEN)
          return { ...state, auth: { ...state.auth, accessToken: '' } }
        }),
      reset: () =>
        set((state) => {
          removeStorage(ACCESS_TOKEN)
          removeStorage(AUTH_USER)
          return {
            ...state,
            auth: { ...state.auth, user: null, accessToken: '' },
          }
        }),
    },
  }
})
