import { ref, onMounted, watch, toValue, type MaybeRefOrGetter } from 'vue'
import { toast } from 'vue-sonner'
import { useSemanticModelsStore } from '@/stores/semantic-models'

type LoadHook = (context: { isReload: boolean }) => void | Promise<void>

interface UseVersionLoaderOptions {
  modelId: MaybeRefOrGetter<string>
  versionId: MaybeRefOrGetter<string>
  onBeforeLoad?: LoadHook
  onAfterLoad?: LoadHook
  onError?: (error: unknown) => void
  errorMessage?: string
}

export function useVersionLoader(options: UseVersionLoaderOptions) {
  const store = useSemanticModelsStore()
  const isLoading = ref(true)

  async function load(isReload: boolean) {
    const currentModelId = toValue(options.modelId)
    const currentVersionId = toValue(options.versionId)

    if (!currentModelId || !currentVersionId) {
      isLoading.value = false
      return
    }

    isLoading.value = true
    try {
      await options.onBeforeLoad?.({ isReload })

      if (!isReload) {
        await store.loadModel(currentModelId)
      }

      const shouldLoadVersion = isReload || store.currentVersion?.id !== currentVersionId
      if (shouldLoadVersion) {
        await store.loadVersion(currentModelId, currentVersionId)
      }

      await options.onAfterLoad?.({ isReload })
    } catch (error) {
      if (options.onError) {
        options.onError(error)
      } else {
        toast.error(options.errorMessage || 'Failed to load version')
      }
    } finally {
      isLoading.value = false
    }
  }

  onMounted(() => {
    void load(false)
  })

  watch(
    () => toValue(options.versionId),
    (newVersionId, oldVersionId) => {
      if (!newVersionId || newVersionId === oldVersionId) return
      void load(true)
    }
  )

  return {
    isLoading,
    reload: () => load(true),
  }
}
