import apiFetch from "@/lib/apiFetch";
import {
   ActionIcon,
   Button,
   Divider,
   Flex,
   Group,
   Input,
   Modal,
   Stack,
   Table,
   Text,
   Title,
   Tooltip
} from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { IconEdit, IconPlus, IconTrash } from "@tabler/icons-react";
import type { JsonValue } from "generated/prisma/runtime/library";
import { useState } from "react";
import useSWR from "swr";
import listMenu from "../lib/listPermission.json";
import notification from "./notificationGlobal";
import PermissionRole from "./PermissionRole";
import PermissionTree from "./PermissionTree";

interface MenuNode {
   key: string;
   label: string;
   default: boolean;
   children?: MenuNode[];
}

export default function UserRoleSetting({ permissions }: { permissions: JsonValue[] }) {
   const [btnDisable, setBtnDisable] = useState(true);
   const [btnLoading, setBtnLoading] = useState(false);
   const [opened, { open, close }] = useDisclosure(false);
   const [openedDelete, { open: openDelete, close: closeDelete }] =
      useDisclosure(false);
   const [dataDelete, setDataDelete] = useState("");
   const {
      data: dataRole,
      mutate: mutateRole,
      isLoading: isLoadingRole,
   } = useSWR("user-role", () => apiFetch.api.user.role.get());
   const [openedTambah, { open: openTambah, close: closeTambah }] =
      useDisclosure(false);
   const { data, mutate, isLoading } = useSWR("role-list", () =>
      apiFetch.api.user.role.get(),
   );
   const list = data?.data || [];
   const listRole = dataRole?.data || [];
   const [dataEdit, setDataEdit] = useState({
      id: "",
      name: "",
      permissions: [],
   });
   const [dataTambah, setDataTambah] = useState({
      name: "",
      permissions: [],
   });
   const [error, setError] = useState({
      name: false,
      permissions: false,
   });

   useShallowEffect(() => {
      mutate();
   }, []);

   async function handleCreate() {
      try {
         setBtnLoading(true);
         const res = await apiFetch.api.user["role-create"].post(dataTambah as any);
         if (res.status === 200) {
            mutate();
            closeTambah();
            setDataTambah({
               name: "",
               permissions: [],
            });
            notification({
               title: "Success",
               message: "Your role have been saved",
               type: "success",
            });
         } else {
            notification({
               title: "Error",
               message: "Failed to create role",
               type: "error",
            });
         }
      } catch (error) {
         console.error(error);
         notification({
            title: "Error",
            message: "Failed to create role",
            type: "error",
         });
      } finally {
         setBtnLoading(false);
      }
   }

   async function handleEdit() {
      try {
         setBtnLoading(true);
         const res = await apiFetch.api.user["role-update"].post(dataEdit as any);
         if (res.status === 200) {
            mutate();
            close();
            notification({
               title: "Success",
               message: "Your role have been saved",
               type: "success",
            });
         } else {
            notification({
               title: "Error",
               message: "Failed to edit role",
               type: "error",
            });
         }
      } catch (error) {
         console.error(error);
         notification({
            title: "Error",
            message: "Failed to edit role",
            type: "error",
         });
      } finally {
         setBtnLoading(false);
      }
   }

   async function handleDelete() {
      try {
         setBtnLoading(true);
         const res = await apiFetch.api.user["role-delete"].post({ id: dataDelete });
         if (res.status === 200) {
            mutate();
            closeDelete();
            notification({
               title: "Success",
               message: "Your role have been deleted",
               type: "success",
            });
         } else {
            notification({
               title: "Error",
               message: "Failed to delete role",
               type: "error",
            });
         }
      } catch (error) {
         console.error(error);
         notification({
            title: "Error",
            message: "Failed to delete role",
            type: "error",
         });
      } finally {
         setBtnLoading(false);
      }
   }

   function chooseEdit({ data }: { data: { id: string; name: string; permissions: []; }; }) {
      setDataEdit({
         id: data.id, name: data.name, permissions: data.permissions ? data.permissions : []
      });
      open();
   }

   function onValidation({ kat, value, aksi, }: { kat: "name" | "permission"; value: string | null; aksi: "edit" | "tambah"; }) {
      if (value == null || value.length < 1) {
         setBtnDisable(true);
         setError({ ...error, [kat]: true });
      } else {
         setBtnDisable(false);
         setError({ ...error, [kat]: false });
      }

      if (aksi === "edit") {
         setDataEdit({ ...dataEdit, [kat]: value });
      } else {
         setDataTambah({ ...dataTambah, [kat]: value });
      }
   }

   function buildOrderList(menus: MenuNode[]): string[] {
      const list: string[] = [];

      const traverse = (nodes: MenuNode[]) => {
         nodes.forEach((node) => {
            list.push(node.key);
            if (node.children) traverse(node.children);
         });
      };

      traverse(menus);
      return list;
   }

   function sortByJsonOrder(arrayData: string[]): string[] {
      const orderList = buildOrderList(listMenu.menus);

      return arrayData.sort((a, b) => {
         return orderList.indexOf(a) - orderList.indexOf(b);
      });
   }

   useShallowEffect(() => {
      if (dataEdit.name.length > 0) {
         setBtnDisable(false);
      }
   }, [dataEdit.id]);

   return (
      <>
         {/* Modal Edit */}
         <Modal
            opened={opened}
            onClose={close}
            title={"Edit"}
            overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
            size={"lg"}
         >
            <Stack gap="ld">
               <Input.Wrapper label="Nama Role">
                  <Input
                     value={dataEdit.name}
                     onChange={(e) =>
                        onValidation({
                           kat: "name",
                           value: e.target.value,
                           aksi: "edit",
                        })
                     }
                  />
               </Input.Wrapper>
               <PermissionTree
                  selected={dataEdit.permissions}
                  onChange={(permissions) => {
                     setDataEdit({ ...dataEdit, permissions: sortByJsonOrder(permissions) as never[] });
                  }}
               />
               <Group justify="center" grow>
                  <Button variant="light" onClick={close}>
                     Batal
                  </Button>
                  <Button
                     variant="filled"
                     onClick={handleEdit}
                     disabled={
                        btnDisable ||
                        dataEdit.name.length < 1 ||
                        dataEdit.permissions?.length < 1
                     }
                     loading={btnLoading}
                  >
                     Simpan
                  </Button>
               </Group>
            </Stack>
         </Modal>

         {/* Modal Tambah */}
         <Modal
            opened={openedTambah}
            onClose={closeTambah}
            title={"Tambah"}
            overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
            size={"lg"}
         >
            <Stack gap="ld">
               <Input.Wrapper
                  label="Nama Role"
                  description=""
                  error={error.name ? "Field is required" : ""}
               >
                  <Input
                     value={dataTambah.name}
                     onChange={(e) =>
                        onValidation({
                           kat: "name",
                           value: e.target.value,
                           aksi: "tambah",
                        })
                     }
                  />
               </Input.Wrapper>
               <PermissionTree
                  selected={dataTambah.permissions}
                  onChange={(permissions) => {
                     setDataTambah({ ...dataTambah, permissions: sortByJsonOrder(permissions) as never[] });
                  }}
               />
               <Group justify="center" grow>
                  <Button variant="light" onClick={closeTambah}>
                     Batal
                  </Button>
                  <Button
                     variant="filled"
                     onClick={handleCreate}
                     disabled={
                        btnDisable ||
                        dataTambah.name.length < 1 ||
                        dataTambah.permissions.length < 1
                     }
                     loading={btnLoading}
                  >
                     Simpan
                  </Button>
               </Group>
            </Stack>
         </Modal>

         {/* Modal Delete */}
         <Modal
            opened={openedDelete}
            onClose={closeDelete}
            title={"Delete"}
            overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
         >
            <Stack gap="md">
               <Text size="md" color="gray.6">
                  Apakah anda yakin ingin menghapus role ini?
               </Text>
               <Group justify="center" grow>
                  <Button variant="light" onClick={closeDelete}>
                     Batal
                  </Button>
                  <Button
                     variant="filled"
                     color="red"
                     onClick={handleDelete}
                     loading={btnLoading}
                  >
                     Hapus
                  </Button>
               </Group>
            </Stack>
         </Modal>

         <Stack gap={"md"}>
            <Flex align="center" justify="space-between">
               <Title order={4} c="gray.2">
                  Daftar Role
               </Title>
               {
                  permissions.includes('setting.user_role.tambah') && (
                     <Tooltip label="Tambah Role">
                        <Button
                           variant="light"
                           leftSection={<IconPlus size={20} />}
                           onClick={openTambah}
                        >
                           Tambah
                        </Button>
                     </Tooltip>
                  )
               }
            </Flex>
            <Divider my={0} />
            <Stack gap={"md"}>
               <Table highlightOnHover>
                  <Table.Thead>
                     <Table.Tr>
                        <Table.Th>Role</Table.Th>
                        <Table.Th>Permission</Table.Th>
                        <Table.Th>Aksi</Table.Th>
                     </Table.Tr>
                  </Table.Thead>
                  <Table.Tbody>
                     {list.length > 0 ? (
                        list?.map((v: any) => (
                           <Table.Tr key={v.id}>
                              <Table.Td w={"150"}>{v.name}</Table.Td>
                              <Table.Td>
                                 <PermissionRole permissions={v.permissions} />
                              </Table.Td>
                              <Table.Td w={"100"}>
                                 <Group>
                                    <Tooltip label={permissions.includes('setting.user_role.edit') ? "Edit Role" : "Edit Role - Anda tidak memiliki akses"}>
                                       <ActionIcon
                                          variant="light"
                                          size="sm"
                                          style={{ boxShadow: "0 0 8px rgba(0,255,200,0.2)" }}
                                          onClick={() => chooseEdit({ data: v })}
                                          disabled={!permissions.includes('setting.user_role.edit') || v.id == "developer"}
                                       >
                                          <IconEdit size={20} />
                                       </ActionIcon>
                                    </Tooltip>
                                    <Tooltip label={permissions.includes('setting.user_role.delete') ? "Delete Role" : "Delete Role - Anda tidak memiliki akses"}>
                                       <ActionIcon
                                          variant="light"
                                          size="sm"
                                          color="red"
                                          style={{ boxShadow: "0 0 8px rgba(0,255,200,0.2)" }}
                                          onClick={() => {
                                             setDataDelete(v.id);
                                             openDelete();
                                          }}
                                          disabled={!permissions.includes('setting.user_role.delete') || v.id == "developer"}
                                       >
                                          <IconTrash size={20} />
                                       </ActionIcon>
                                    </Tooltip>
                                 </Group>
                              </Table.Td>
                           </Table.Tr>
                        ))
                     ) : (
                        <Table.Tr>
                           <Table.Td colSpan={5} align="center">
                              Data Role Tidak Ditemukan
                           </Table.Td>
                        </Table.Tr>
                     )}
                  </Table.Tbody>
               </Table>
            </Stack>
         </Stack>
      </>
   );
}
