import {
  Button,
  Container,
  FormControl,
  FormLabel,
  Input,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  Table,
  TableCaption,
  TableContainer,
  Tbody,
  Td,
  Th,
  Thead,
  Tr,
  useDisclosure,
  useToast,
} from "@chakra-ui/react";
import { useLoaderData } from "@remix-run/react";
import { useState } from "react";

export async function loader({ context }: { context: RequestContext }) {
  if (!context.data.current_user)
    throw new Response(null, {
      status: 401,
    });

  if (
    ![
      "165594923586945025",
      "289372404541554689",
      "396347223736057866",
    ].includes(context.data.current_user.id)
  )
    throw new Response(null, {
      status: 403,
    });

  return (await context.env.DATA.list({ prefix: "gamemod_" }))?.keys ?? [];
}

export default function () {
  const data: { [k: string]: any }[] = useLoaderData<typeof loader>();
  const [gameModData, setGameModData] = useState(data);
  const { isOpen, onClose, onOpen } = useDisclosure();
  const [idToAdd, setIdToAdd] = useState<string>("");
  const [nameToAdd, setNameToAdd] = useState<string>("");
  const toast = useToast();

  async function addMod(id: string, name: string) {
    const response = await fetch("/api/gme/add", {
      body: JSON.stringify({ name, user: id }),
      headers: {
        "content-type": "application/json",
      },
      method: "POST",
    });

    if (!response.ok) {
      let msg = "Unknown error";

      try {
        msg = ((await response.json()) as { error: string }).error;
      } catch {}

      toast({
        description: msg,
        status: "error",
        title: "Cannot add game mod",
      });
    } else {
      onClose();
      location.reload();
    }

    setIdToAdd("");
    setNameToAdd("");
  }

  async function removeMod(user: string) {
    const response = await fetch("/api/gme/remove", {
      body: JSON.stringify({ user }),
      headers: {
        "content-type": "application/json",
      },
      method: "POST",
    });

    if (!response.ok) {
      let msg = "Unknown error";

      try {
        msg = ((await response.json()) as { error: string }).error;
      } catch {}
      toast({
        description: msg,
        status: "error",
        title: "Cannot remove game mod",
      });

      return;
    }

    toast({
      description: `${data.find((i) => i.metadata.id === user)?.name} was removed as a game mod`,
      status: "success",
      title: "Game mod removed",
    });

    setGameModData(gameModData.filter((i) => i.metadata.id !== user));
  }

  return (
    <Container maxW="container.lg">
      <TableContainer>
        <Table variant="simple">
          <TableCaption>Currently active game mods</TableCaption>
          <Thead>
            <Tr>
              <Th>ID</Th>
              <Th>Name</Th>
              <Th>Added At</Th>
              <Th>Added By</Th>
              <Th>Remove</Th>
            </Tr>
          </Thead>
          <Tbody>
            {gameModData.map((item) => {
              return (
                <Tr key={item.metadata.id}>
                  <Td>{item.metadata.id}</Td>
                  <Td>{item.metadata.name}</Td>
                  <Td>{item.metadata.created_at}</Td>
                  <Td>{item.metadata.created_by}</Td>
                  <Td>
                    <Button
                      onClick={async () => await removeMod(item.metadata.id)}
                    >
                      Remove
                    </Button>
                  </Td>
                </Tr>
              );
            })}
          </Tbody>
        </Table>
      </TableContainer>
      <Button alignSelf="end" mt="16px" onClick={onOpen}>
        Add
      </Button>
      <Modal isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Add Game Mod</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <FormControl>
              <FormLabel>Name</FormLabel>
              <Input
                maxLength={32}
                onChange={(e) => setNameToAdd(e.target.value)}
                value={nameToAdd}
              />
            </FormControl>
            <br />
            <FormControl pt="16px">
              <FormLabel>ID</FormLabel>
              <Input
                maxLength={19}
                onChange={(e) => setIdToAdd(e.target.value)}
                value={idToAdd}
              />
            </FormControl>
          </ModalBody>
          <ModalFooter gap="8px">
            <Button
              onClick={() => {
                onClose();
                setIdToAdd("");
                setNameToAdd("");
              }}
            >
              Cancel
            </Button>
            <Button
              colorScheme="blue"
              disabled={
                !idToAdd.match(/\d{17,19}/) ||
                nameToAdd.length < 1 ||
                nameToAdd.length > 32
              }
              onClick={async () => {
                await addMod(idToAdd, nameToAdd);
              }}
            >
              Add
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </Container>
  );
}
