import type {
  DSLImportMode,
  DSLImportResponse,
} from '@/models/app'
import type { AppIconType } from '@/types/app'
import { toast } from '@langgenius/dify-ui/toast'
import {
  useCallback,
  useRef,
  useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import { useSelector } from '@/context/app-context'
import { DSLImportStatus } from '@/models/app'
import { useRouter } from '@/next/navigation'
import {
  importDSL,
  importDSLConfirm,
} from '@/service/apps'
import { getRedirection } from '@/utils/app-redirection'

type DSLPayload = {
  mode: DSLImportMode
  yaml_content?: string
  yaml_url?: string
  name?: string
  icon_type?: AppIconType
  icon?: string
  icon_background?: string
  description?: string
}
type ResponseCallback = {
  onSuccess?: (payload: DSLImportResponse) => void
  onPending?: (payload: DSLImportResponse) => void
  onFailed?: () => void
}
export const useImportDSL = () => {
  const { t } = useTranslation()
  const [isFetching, setIsFetching] = useState(false)
  const { handleCheckPluginDependencies } = usePluginDependencies()
  const isCurrentWorkspaceEditor = useSelector(s => s.isCurrentWorkspaceEditor)
  const { push } = useRouter()
  const [versions, setVersions] = useState<{ importedVersion: string, systemVersion: string }>()
  const importIdRef = useRef<string>('')

  const handleImportDSL = useCallback(async (
    payload: DSLPayload,
    {
      onSuccess,
      onPending,
      onFailed,
    }: ResponseCallback,
  ) => {
    if (isFetching)
      return
    setIsFetching(true)

    try {
      const response = await importDSL(payload)

      if (!response)
        return

      const {
        id,
        status,
        app_id,
        app_mode,
        imported_dsl_version,
        current_dsl_version,
      } = response

      if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) {
        if (!app_id)
          return

        const message = t(status === DSLImportStatus.COMPLETED ? 'newApp.appCreated' : 'newApp.caution', { ns: 'app' })
        const description = status === DSLImportStatus.COMPLETED_WITH_WARNINGS
          ? t('newApp.appCreateDSLWarning', { ns: 'app' })
          : undefined

        if (status === DSLImportStatus.COMPLETED)
          toast.success(message)
        else
          toast.warning(message, { description })
        onSuccess?.(response)
        localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
        await handleCheckPluginDependencies(app_id)
        getRedirection(isCurrentWorkspaceEditor, { id: app_id, mode: app_mode }, push)
      }
      else if (status === DSLImportStatus.PENDING) {
        setVersions({
          importedVersion: imported_dsl_version ?? '',
          systemVersion: current_dsl_version ?? '',
        })
        importIdRef.current = id
        onPending?.(response)
      }
      else {
        toast.error(t('newApp.appCreateFailed', { ns: 'app' }))
        onFailed?.()
      }
    }
    catch {
      toast.error(t('newApp.appCreateFailed', { ns: 'app' }))
      onFailed?.()
    }
    finally {
      setIsFetching(false)
    }
  }, [t, handleCheckPluginDependencies, isCurrentWorkspaceEditor, push, isFetching])

  const handleImportDSLConfirm = useCallback(async (
    {
      onSuccess,
      onFailed,
    }: Pick<ResponseCallback, 'onSuccess' | 'onFailed'>,
  ) => {
    if (isFetching)
      return
    setIsFetching(true)
    if (!importIdRef.current)
      return

    try {
      const response = await importDSLConfirm({
        import_id: importIdRef.current,
      })

      const { status, app_id, app_mode } = response
      if (!app_id)
        return

      if (status === DSLImportStatus.COMPLETED) {
        onSuccess?.(response)
        toast.success(t('newApp.appCreated', { ns: 'app' }))
        await handleCheckPluginDependencies(app_id)
        localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
        getRedirection(isCurrentWorkspaceEditor, { id: app_id!, mode: app_mode }, push)
      }
      else if (status === DSLImportStatus.FAILED) {
        toast.error(t('newApp.appCreateFailed', { ns: 'app' }))
        onFailed?.()
      }
    }
    catch {
      toast.error(t('newApp.appCreateFailed', { ns: 'app' }))
      onFailed?.()
    }
    finally {
      setIsFetching(false)
    }
  }, [t, handleCheckPluginDependencies, isCurrentWorkspaceEditor, push, isFetching])

  return {
    handleImportDSL,
    handleImportDSLConfirm,
    versions,
    isFetching,
  }
}
