'use client'

import type { SnippetDetail } from '@/models/snippet'
import {
  AlertDialog,
  AlertDialogActions,
  AlertDialogCancelButton,
  AlertDialogConfirmButton,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogTitle,
} from '@langgenius/dify-ui/alert-dialog'
import { cn } from '@langgenius/dify-ui/cn'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@langgenius/dify-ui/dropdown-menu'
import { toast } from '@langgenius/dify-ui/toast'
import { useAtomValue } from 'jotai'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { CreateSnippetDialog } from '@/app/components/snippets/create-snippet-dialog'
import {
  canCreateAndModifySnippets,
  canManageSnippets,
} from '@/app/components/snippets/utils/permission'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { useRouter } from '@/next/navigation'
import {
  useDeleteSnippetMutation,
  useExportSnippetMutation,
  useUpdateSnippetMutation,
} from '@/service/use-snippets'
import { downloadBlob } from '@/utils/download'

type SnippetInfoDropdownProps = {
  snippet: SnippetDetail
}

const SnippetInfoDropdown = ({ snippet }: SnippetInfoDropdownProps) => {
  const { t } = useTranslation('snippet')
  const { replace } = useRouter()
  const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom)
  const [open, setOpen] = React.useState(false)
  const [isEditDialogOpen, setIsEditDialogOpen] = React.useState(false)
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = React.useState(false)
  const updateSnippetMutation = useUpdateSnippetMutation()
  const exportSnippetMutation = useExportSnippetMutation()
  const deleteSnippetMutation = useDeleteSnippetMutation()
  const canCreateAndModifySnippet = canCreateAndModifySnippets(workspacePermissionKeys)
  const canManageSnippet = canManageSnippets(workspacePermissionKeys)
  const canShowOperations = canCreateAndModifySnippet || canManageSnippet

  const initialValue = React.useMemo(
    () => ({
      name: snippet.name,
      description: snippet.description ?? undefined,
    }),
    [snippet.description, snippet.name],
  )

  const handleOpenEditDialog = React.useCallback(() => {
    setOpen(false)
    setIsEditDialogOpen(true)
  }, [])

  const handleExportSnippet = React.useCallback(async () => {
    if (!canCreateAndModifySnippet) return

    setOpen(false)
    try {
      const data = await exportSnippetMutation.mutateAsync({ snippetId: snippet.id })
      const file = new Blob([data], { type: 'application/yaml' })
      downloadBlob({ data: file, fileName: `${snippet.name}.yml` })
    } catch {
      toast.error(t(($) => $.exportFailed))
    }
  }, [canCreateAndModifySnippet, exportSnippetMutation, snippet.id, snippet.name, t])

  const handleEditSnippet = React.useCallback(
    async ({ name, description }: { name: string; description: string }) => {
      updateSnippetMutation.mutate(
        {
          params: { snippetId: snippet.id },
          body: {
            name,
            description,
          },
        },
        {
          onSuccess: () => {
            toast.success(t(($) => $.editDone))
            setIsEditDialogOpen(false)
          },
          onError: (error) => {
            toast.error(error instanceof Error ? error.message : t(($) => $.editFailed))
          },
        },
      )
    },
    [snippet.id, t, updateSnippetMutation],
  )

  const handleDeleteSnippet = React.useCallback(() => {
    deleteSnippetMutation.mutate(
      {
        params: { snippetId: snippet.id },
      },
      {
        onSuccess: () => {
          toast.success(t(($) => $.deleted))
          setIsDeleteDialogOpen(false)
          replace('/snippets')
        },
        onError: (error) => {
          toast.error(error instanceof Error ? error.message : t(($) => $.deleteFailed))
        },
      },
    )
  }, [deleteSnippetMutation, replace, snippet.id, t])

  if (!canShowOperations) return null

  return (
    <>
      <DropdownMenu open={open} onOpenChange={setOpen}>
        <DropdownMenuTrigger
          className={cn(
            'action-btn action-btn-m size-6 rounded-md text-text-tertiary',
            open && 'bg-state-base-hover text-text-secondary',
          )}
        >
          <span aria-hidden className="i-ri-more-fill size-4" />
        </DropdownMenuTrigger>
        <DropdownMenuContent placement="bottom-end" sideOffset={4} popupClassName="w-[180px] p-1">
          {canCreateAndModifySnippet && (
            <>
              <DropdownMenuItem className="mx-0 gap-2" onClick={handleOpenEditDialog}>
                <span aria-hidden className="i-ri-edit-line size-4 shrink-0 text-text-tertiary" />
                <span className="grow">{t(($) => $['menu.editInfo'])}</span>
              </DropdownMenuItem>
              <DropdownMenuItem className="mx-0 gap-2" onClick={handleExportSnippet}>
                <span
                  aria-hidden
                  className="i-ri-download-2-line size-4 shrink-0 text-text-tertiary"
                />
                <span className="grow">{t(($) => $['menu.exportSnippet'])}</span>
              </DropdownMenuItem>
            </>
          )}
          {canManageSnippet && (
            <>
              {canCreateAndModifySnippet && (
                <DropdownMenuSeparator className="my-1! bg-divider-subtle" />
              )}
              <DropdownMenuItem
                className="mx-0 gap-2"
                variant="destructive"
                onClick={() => {
                  setOpen(false)
                  setIsDeleteDialogOpen(true)
                }}
              >
                <span aria-hidden className="i-ri-delete-bin-line size-4 shrink-0" />
                <span className="grow">{t(($) => $['menu.deleteSnippet'])}</span>
              </DropdownMenuItem>
            </>
          )}
        </DropdownMenuContent>
      </DropdownMenu>

      {isEditDialogOpen && (
        <CreateSnippetDialog
          isOpen={isEditDialogOpen}
          initialValue={initialValue}
          title={t(($) => $.editDialogTitle)}
          confirmText={t(($) => $['operation.save'], { ns: 'common' })}
          isSubmitting={updateSnippetMutation.isPending}
          onClose={() => setIsEditDialogOpen(false)}
          onConfirm={handleEditSnippet}
        />
      )}

      <AlertDialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
        <AlertDialogContent className="w-100">
          <div className="space-y-2 p-6">
            <AlertDialogTitle className="title-md-semi-bold text-text-primary">
              {t(($) => $.deleteConfirmTitle)}
            </AlertDialogTitle>
            <AlertDialogDescription className="system-sm-regular text-text-tertiary">
              {t(($) => $.deleteConfirmContent)}
            </AlertDialogDescription>
          </div>
          <AlertDialogActions className="pt-0">
            <AlertDialogCancelButton>
              {t(($) => $['operation.cancel'], { ns: 'common' })}
            </AlertDialogCancelButton>
            <AlertDialogConfirmButton
              loading={deleteSnippetMutation.isPending}
              onClick={handleDeleteSnippet}
            >
              {t(($) => $['menu.deleteSnippet'])}
            </AlertDialogConfirmButton>
          </AlertDialogActions>
        </AlertDialogContent>
      </AlertDialog>
    </>
  )
}

export default React.memo(SnippetInfoDropdown)
