import { useCallback, useEffect, useState } from "react"
import { toast } from "sonner"
import { getAllPermissions } from "@/actions/permission"
import { updateRole } from "@/actions/role"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
import { cn } from "@/lib/utils"
import type { Role } from "@/models/role"

type TreeNode = {
  id: number
  name: string
  description: string
  children: TreeNode[]
}

function PermissionRow({
  node,
  depth,
  selected,
  onToggle,
}: {
  node: TreeNode
  depth: number
  selected: Set<number>
  onToggle: (id: number, checked: boolean) => void
}) {
  const hasChildren = node.children.length > 0

  return (
    <>
      <div className={cn("flex items-center gap-2 h-8", hasChildren && "mt-2")}>
        <div style={{ width: depth * 16 }} />
        <Checkbox
          id={`perm-${node.id}`}
          checked={selected.has(node.id)}
          onCheckedChange={checked => onToggle(node.id, checked === true)}
        />
        <label
          htmlFor={`perm-${node.id}`}
          className={cn(
            "cursor-pointer select-none text-sm size-full flex items-center",
            hasChildren && "font-bold",
          )}
        >
          {node.description}
        </label>
      </div>
      {node.children.map(child => (
        <PermissionRow
          key={child.id}
          node={child}
          depth={depth + 1}
          selected={selected}
          onToggle={onToggle}
        />
      ))}
    </>
  )
}

export function AssignPermissions(props: {
  role: Role
  onSuccess?: () => void
}) {
  const [open, setOpen] = useState(false)
  const [loading, setLoading] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [nodes, setNodes] = useState<TreeNode[]>([])
  const [selected, setSelected] = useState<Set<number>>(new Set())

  const fetchPermissions = useCallback(async () => {
    setLoading(true)
    try {
      const resp = await getAllPermissions()
      if (!resp.success) throw new Error(resp.message)

      const data = resp.data ?? []

      const map = new Map<number, TreeNode>()
      data.forEach(p => {
        map.set(p.id, {
          id: p.id,
          name: p.name,
          description: p.description,
          children: [],
        })
      })

      const roots: TreeNode[] = []
      data.forEach(p => {
        const node = map.get(p.id)
        if (!node) return
        if (!p.parent_id) {
          roots.push(node)
        } else {
          map.get(p.parent_id)?.children.push(node)
        }
      })

      setNodes(roots)
    } catch (error) {
      toast.error(error instanceof Error ? error.message : "获取权限列表失败")
    } finally {
      setLoading(false)
    }
  }, [])

  useEffect(() => {
    if (open) fetchPermissions()
  }, [open, fetchPermissions])

  const handleToggle = useCallback((id: number, checked: boolean) => {
    setSelected(prev => {
      const next = new Set(prev)
      if (checked) {
        next.add(id)
      } else {
        next.delete(id)
      }
      return next
    })
  }, [])

  const handleSubmit = async () => {
    setSubmitting(true)
    try {
      const resp = await updateRole({
        id: props.role.id,
        permissions: Array.from(selected),
      })
      if (resp.success) {
        toast.success("权限分配成功")
        props.onSuccess?.()
        setOpen(false)
      } else {
        toast.error(resp.message ?? "权限分配失败")
      }
    } catch (error) {
      toast.error(error instanceof Error ? error.message : "接口请求错误")
    } finally {
      setSubmitting(false)
    }
  }

  const handleOpenChange = (value: boolean) => {
    if (value) {
      setSelected(new Set((props.role.permissions ?? []).map(p => p.id)))
    } else {
      setSelected(new Set())
      setNodes([])
    }
    setOpen(value)
  }

  return (
    <Dialog open={open} onOpenChange={handleOpenChange}>
      <DialogTrigger asChild>
        <Button size="sm" variant="secondary">
          分配权限
        </Button>
      </DialogTrigger>

      <DialogContent className="max-w-md">
        <DialogHeader>
          <DialogTitle>分配权限 · {props.role.name}</DialogTitle>
        </DialogHeader>

        <div className="max-h-[60vh] overflow-y-auto pr-1">
          {loading ? (
            <div className="py-8 text-center text-sm text-muted-foreground">
              加载中...
            </div>
          ) : nodes.length === 0 ? (
            <div className="py-8 text-center text-sm text-muted-foreground">
              暂无权限数据
            </div>
          ) : (
            <div className="flex flex-col">
              {nodes.map(node => (
                <PermissionRow
                  key={node.id}
                  node={node}
                  depth={0}
                  selected={selected}
                  onToggle={handleToggle}
                />
              ))}
            </div>
          )}
        </div>

        <DialogFooter>
          <DialogClose asChild>
            <Button variant="ghost">取消</Button>
          </DialogClose>
          <Button onClick={handleSubmit} disabled={submitting || loading}>
            {submitting ? "保存中..." : "保存"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
