"use client";
import { useMutation, useQuery } from "@tanstack/react-query";
import * as _ from "lodash";
import { Check, Search } from "lucide-react";
import { useEffect, useState, type ReactNode } from "react";
import { resourceApi } from "~/api/resource-api.service";
import Loader from "~/components/loader";
import { Button } from "~/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "~/components/ui/dialog";
import { Input } from "~/components/ui/input";
import { ScrollArea } from "~/components/ui/scroll-area";
import { delay } from "~/features/delay";
import { RoleResourceItem } from "./role-resource-item";
import { useDebounce } from "use-debounce";
import InputSearch from "~/components/input-search";
import { ConfirmAlert } from "~/components/btn/confirm-alert";
interface RoleResourceModalProps {
  role: IRole;
  allResources: IResource[];
  onUpdateRole?: (updatedRole: IRole) => void;
  children?: ReactNode;
}

export default function RoleResourceModal({
  role,
  onUpdateRole,
  children,
}: RoleResourceModalProps) {
  const [open, setOpen] = useState(false);
  const [searchTerm, setSearchTerm] = useState("");
  const [selectedResources, setSelectedResources] = useState<Set<number>>(
    new Set([])
  );

  const [search] = useDebounce(searchTerm, 400);

  const { data, isPending, refetch } = useQuery({
    queryKey: ["resources/role/selected", { role_id: role.id, search }],
    queryFn: async () => {
      await delay(300);

      return resourceApi.resourceByRole(
        role.id,
        search.length ? { search } : {}
      );
    },
  });

  function getCheckedIds(arr: IResource[]) {
    return _.flatMap(arr, (item) => {
      const selfIds = item.checked ? [item.id] : [];
      const childIds: IResource["id"][] = getCheckedIds(item.children || []);
      return [...selfIds, ...childIds];
    });
  }

  const updateMutation = useMutation({
    mutationFn: async (values: {
      role_id: IRole["id"];
      resource_ids: number[];
    }) => {
      await delay(300);

      return resourceApi.customAction(values.role_id, "role", values, "PUT");
    },
    onSuccess: (data) => {
      refetch();
    },
  });

  const handleSave = () => {
    // setOpen(false);

    updateMutation.mutate({
      role_id: role.id,
      resource_ids: Array.from(selectedResources),
    });
  };

  const handleCancel = () => {
    setOpen(false);
  };

  const handleToggleResource = (resource: IResource, parent?: IResource) => {
    const newSelected = new Set(selectedResources);

    const removeChildren = (res: IResource) => {
      res.children.forEach((child) => {
        newSelected.delete(child.id);
        removeChildren(child);
      });
    };

    const addChildren = (res: IResource) => {
      res.children.forEach((child) => {
        if (!child.is_public) {
          newSelected.add(child.id);
          addChildren(child);
        }
      });
    };

    if (newSelected.has(resource.id)) {
      // Bỏ chọn resource này
      newSelected.delete(resource.id);
      removeChildren(resource);

      // Nếu cha không còn con nào được chọn -> bỏ chọn cha
      if (
        parent &&
        !parent.children.some((child) => newSelected.has(child.id))
      ) {
        newSelected.delete(parent.id);
      }
    } else {
      // Chọn resource này
      newSelected.add(resource.id);
      addChildren(resource);

      if (parent) {
        if (!newSelected.has(parent.id)) {
          newSelected.add(parent.id);
        }
      }
    }

    setSelectedResources(newSelected);
  };

  useEffect(() => {
    if (!data?.data) return;

    const ids = new Set(getCheckedIds(data.data));

    setSelectedResources(ids);
  }, [data]);

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>{children}</DialogTrigger>
      <DialogContent className="max-w-4xl max-h-[80vh]">
        <DialogHeader>
          <DialogTitle>
            Cấu hình tài nguyên cho vai trò: {role.role_name}
          </DialogTitle>
          <DialogDescription>
            Thêm hoặc xoá tài nguyên khỏi vai trò này.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4">
          {/* Tìm kiếm */}

          <InputSearch
            placeholder="Tìm kiếm tài nguyên..."
            value={searchTerm}
            onChange={(e) => setSearchTerm(e.target.value)}
          />

          <ScrollArea className="h-[400px] w-full border rounded-md p-4">
            {!isPending && data?.data?.length === 0 ? (
              <div className="text-center text-gray-500 dark:text-gray-400 py-8">
                Không tìm thấy tài nguyên phù hợp
              </div>
            ) : (
              <div className="space-y-1">
                {data?.data?.map((resource: IResource) => (
                  <RoleResourceItem
                    key={resource.id}
                    resource={resource}
                    isSelected={selectedResources.has(resource.id)}
                    onToggle={handleToggleResource}
                    selectedResources={selectedResources}
                  />
                ))}
              </div>
            )}

            {isPending && (
              <div className="flex items-center justify-center h-[360px]">
                <Loader />
              </div>
            )}
          </ScrollArea>
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={handleCancel}>
            Hủy
          </Button>
          <ConfirmAlert
            title="Xác nhận lưu thay đổi"
            description="Bạn có chắc muốn lưu các thay đổi quyền tài nguyên cho vai trò này? Thao tác này sẽ ảnh hưởng đến quyền truy cập của người dùng trong vai trò."
            onConfirm={handleSave}
          >
            <Button disabled={updateMutation.isPending}>
              {updateMutation.isPending ? (
                <Loader color="white" />
              ) : (
                <>
                  <Check className="mr-1 w-4 h-4" />
                  Lưu
                </>
              )}
            </Button>
          </ConfirmAlert>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
