import { useStorage } from '@vueuse/core'
import { isEeUI } from '#imports'

export interface WorkspaceSettings {
  data: {
    showOtherUserPersonalViews?: boolean
    // any other ws level keys we can store here
    [key: string]: any
  }
  lastAccessed: number // TTL and tracking
}

export interface UserLocalStorageInfo {
  [userId: string]: {
    [workspaceId: string]: WorkspaceSettings
  }
}

export class UserLocalStorageInfoManager {
  private storage: Ref<UserLocalStorageInfo>
  private readonly TTL = 180 * 24 * 60 * 60 * 1000 // 180 days
  private readonly defaultData: WorkspaceSettings['data'] = {
    showOtherUserPersonalViews: true,
  }

  constructor() {
    this.storage = useStorage<UserLocalStorageInfo>('nc-user-local-storage-info', {})
    this.cleanExpired()
  }

  /** Cleanup expired workspace settings */
  private cleanExpired(): void {
    if (!isEeUI) return

    const now = Date.now()
    const data = this.storage.value

    Object.keys(data).forEach((userId) => {
      const workspaces = data[userId]
      if (!workspaces) return

      Object.keys(workspaces).forEach((wsId) => {
        if (now - workspaces[wsId]!.lastAccessed > this.TTL) {
          delete workspaces[wsId]
        }
      })

      // remove user entirely if no workspaces left
      if (Object.keys(workspaces).length === 0) {
        delete data[userId]
      }
    })
  }

  /** Cleanup local storage workspaces that no longer exist */
  cleanMissingWorkspaces(userId: string, workspaceIds: string[]): void {
    if (!isEeUI) return

    const userWorkspaces = this.storage.value[userId]
    if (!userWorkspaces) return

    Object.keys(userWorkspaces).forEach((wsId) => {
      if (!workspaceIds.includes(wsId)) {
        delete userWorkspaces[wsId]
      } else {
        this.touch(userId, wsId)
      }
    })

    // Remove user if no workspace left
    if (Object.keys(userWorkspaces).length === 0) {
      delete this.storage.value[userId]
    }
  }

  /** Ensure workspace exists for user */
  private ensureWorkspace(userId: string, workspaceId: string): void {
    if (!isEeUI) return

    if (!userId || !workspaceId) return

    if (!this.storage.value[userId]) this.storage.value[userId] = {}

    if (!this.storage.value[userId][workspaceId]) {
      this.storage.value[userId][workspaceId] = {
        data: {},
        lastAccessed: Date.now(),
      }
    }
  }

  /** Update lastAccessed timestamp */
  private touch(userId: string, workspaceId: string): void {
    if (!userId || !workspaceId || !isEeUI) return

    if (this.storage.value[userId]?.[workspaceId]) {
      this.storage.value[userId][workspaceId].lastAccessed = Date.now()
    } else {
      this.storage.value[userId] = {
        ...(this.storage.value[userId] || {}),
        [workspaceId]: {
          data: {},
          lastAccessed: Date.now(),
        },
      }
    }
  }

  /** Get a workspace-level key */
  get(userId: string, workspaceId: string, key: keyof WorkspaceSettings['data'], defaultValue: any = null): any {
    if (!userId || !workspaceId || !isEeUI) return defaultValue

    this.touch(userId, workspaceId)

    if (defaultValue !== null && ncIsUndefined(this.storage.value[userId]![workspaceId]!.data[key])) {
      this.storage.value[userId]![workspaceId]!.data[key] = defaultValue
    }

    return this.storage.value[userId]![workspaceId]!.data[key]
  }

  /** Set a workspace-level key */
  set(userId: string, workspaceId: string, key: string, value: any): void {
    if (!userId || !workspaceId || !key || !isEeUI) return

    this.ensureWorkspace(userId, workspaceId)
    this.storage.value[userId]![workspaceId]!.data[key] = value
    this.touch(userId, workspaceId)
  }

  /** Clear workspace for user */
  clearWorkspace(userId: string, workspaceId: string): void {
    if (!userId || !workspaceId || !isEeUI) return

    if (this.storage.value[userId]?.[workspaceId]) {
      delete this.storage.value[userId][workspaceId]
    }
  }

  /** Clear all data for a user */
  clearUser(userId: string): void {
    if (!userId || !isEeUI) return

    if (this.storage.value[userId]) {
      delete this.storage.value[userId]
    }
  }
}

export const userLocalStorageInfoManager = new UserLocalStorageInfoManager()
