import { useEffect, useState } from 'react'

import { toast } from 'sonner'

import { assignSysRoleMenus, getAllSysMenus, getSysRoleMenus } from '@/api'
import { CheckboxTree, useCheckboxTree, type CheckboxTreeNode } from '@/components/checkbox-tree'
import { DialogSkeleton } from '@/components/dialog-skeleton'
import { Button } from '@/components/ui/button.tsx'
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog.tsx'
import { Spinner } from '@/components/ui/spinner.tsx'
import type { SysMenu, SysRole } from '@/schemas'

interface Props {
  currentRow?: SysRole | null
  onClose: () => void
  onConfirm: () => void
  open: boolean
}

const buildTreeData = (data: SysMenu[], parentId: string | null = null): CheckboxTreeNode[] => {
  return data
    .filter((item) => (item.parent_id?.toString() ?? null) === parentId)
    .map((item) => {
      const children = buildTreeData(data, item.id.toString())
      return {
        id: item.id.toString(),
        label: item.name,
        data: item,
        children: children.length > 0 ? children : [],
      }
    })
}

export function AssignMenusDialog({ open, onClose, onConfirm, currentRow }: Props) {
  const [treeData, setTreeData] = useState<CheckboxTreeNode[]>([])
  const { getNodeState, toggleNode, setCheckedIds, getCheckedIdsWithParents } = useCheckboxTree(
    treeData,
    [],
  )
  const [loading, setLoading] = useState(false)
  const [skeletonLoading, setSkeletonLoading] = useState(true)

  useEffect(() => {
    const fetchMenus = async () => {
      setSkeletonLoading(true)

      const { data: menus } = await getAllSysMenus()
      const { data: checkedMenus } = await getSysRoleMenus(currentRow?.id as number)
      setTreeData(buildTreeData(menus))
      setCheckedIds(checkedMenus.map((item) => item.id.toString()))

      setSkeletonLoading(false)
    }

    if (open && currentRow?.id) fetchMenus()
  }, [open, currentRow, setCheckedIds])

  const handleConfirm = async () => {
    try {
      setLoading(true)
      await assignSysRoleMenus(
        currentRow?.id as number,
        getCheckedIdsWithParents().map((item) => parseInt(item)),
      )
      toast('操作成功！')
      onConfirm()
    } finally {
      setLoading(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={onClose}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>分配菜单权限</DialogTitle>
          <DialogDescription />
        </DialogHeader>

        <div className='h-125 overflow-y-auto'>
          <DialogSkeleton rows={20} loading={skeletonLoading}>
            <CheckboxTree
              data={treeData}
              getNodeState={getNodeState}
              onToggle={toggleNode}
              renderLabel={(node: CheckboxTreeNode) => (
                <div className='flex gap-2'>
                  <div>{node.data?.name}</div>
                </div>
              )}
            />
          </DialogSkeleton>
        </div>

        <DialogFooter>
          <DialogClose asChild>
            <Button disabled={loading} variant='outline'>
              取消
            </Button>
          </DialogClose>
          <Button disabled={loading} onClick={handleConfirm}>
            保存
            {loading && <Spinner data-icon='inline-start' />}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
