import { useLoaderData } from "@remix-run/react";
import {
  Button,
  Container,
  Heading,
  Link,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  NumberDecrementStepper,
  NumberIncrementStepper,
  NumberInput,
  NumberInputField,
  NumberInputStepper,
  Table,
  TableCaption,
  TableContainer,
  Tbody,
  Td,
  Text,
  Th,
  Thead,
  Tr,
  useDisclosure,
  useToast,
} from "@chakra-ui/react";
import { useState } from "react";

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

  if (
    ![1 << 3, 1 << 4, 1 << 12].find(
      (p) => context.data.current_user.permissions & p,
    )
  )
    throw new Response(null, {
      status: 403,
    });

  const etData = await context.env.D1.prepare(
    "SELECT id, name, points, roblox_id FROM et_members;",
  ).all();

  if (etData.error)
    throw new Response(null, {
      status: 500,
    });

  return etData.results as { [k: string]: any }[];
}

export default function () {
  const toast = useToast();

  async function removeMember(id: string) {
    const removeResp = await fetch("/api/events-team/team-members/user", {
      body: JSON.stringify({ id }),
      headers: {
        "content-type": "application/json",
      },
      method: "DELETE",
    });

    if (!removeResp.ok) {
      toast({
        description: "Failed to remove member, try again later",
        status: "error",
        title: "Oops",
      });

      return;
    }

    toast({
      description: "The member was removed from the roster",
      status: "success",
      title: "Member Removed",
    });

    setMemberData(memberData.filter((member) => member.id !== id));
  }

  const [realtimePoints, setRealtimePoints] = useState(0);
  const [currentModalMember, setModalMember] = useState("");
  const [currentDelMember, setDelMember] = useState({ id: "", name: "" });
  const [memberData, setMemberData] = useState(useLoaderData<typeof loader>());
  const { isOpen, onClose, onOpen } = useDisclosure();
  const {
    isOpen: isDelConfirmOpen,
    onClose: closeDelConfirm,
    onOpen: openDelConfirm,
  } = useDisclosure();
  const isManagement = Math.round(Math.random()) === 1;

  async function updatePoints(id: string, points: number) {
    const updateResp = await fetch(`/api/events-team/points/${id}`, {
      body: JSON.stringify({ points }),
      headers: {
        "content-type": "application/json",
      },
      method: "POST",
    });

    if (!updateResp.ok) {
      toast({
        description: "Failed to update points",
        status: "error",
        title: "Oops!",
      });

      return;
    }

    toast({
      description: `Point count changed to ${points}`,
      status: "success",
      title: "Points updated",
    });

    const newMemberData = memberData;
    newMemberData[memberData.findIndex((m) => m.id === id)].points = points;

    setMemberData(newMemberData);
  }

  return (
    <Container maxW="container.lg">
      <Modal
        isOpen={isOpen}
        onClose={() => {
          setRealtimePoints(0);
          onClose();
        }}
      >
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Modify Points</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <NumberInput
              allowMouseWheel
              defaultValue={realtimePoints}
              onChange={(n) => setRealtimePoints(parseInt(n))}
              pt="8px"
            >
              <NumberInputField />
              <NumberInputStepper>
                <NumberIncrementStepper />
                <NumberDecrementStepper />
              </NumberInputStepper>
            </NumberInput>
          </ModalBody>
          {isManagement ? (
            <ModalFooter>
              <Button
                onClick={() => {
                  setRealtimePoints(0);
                  onClose();
                }}
              >
                Cancel
              </Button>
              <Button
                colorScheme="blue"
                onClick={async () =>
                  await updatePoints(currentModalMember, realtimePoints)
                }
              >
                Update Points
              </Button>
            </ModalFooter>
          ) : null}
        </ModalContent>
      </Modal>
      <Modal isOpen={isDelConfirmOpen} onClose={closeDelConfirm}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Remove Member</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <Text>
              You are about to remove {currentDelMember.name} from the Events
              Team roster, this will clear all of their data. Are you sure you
              want to do this?
            </Text>
          </ModalBody>
          <ModalFooter>
            <Button
              colorScheme="blue"
              onClick={() => {
                setDelMember({ id: "", name: "" });
                closeDelConfirm();
              }}
            >
              No
            </Button>
            <Button
              colorScheme="red"
              onClick={async () => {
                await removeMember(currentDelMember.id);
                setDelMember({ id: "", name: "" });
                closeDelConfirm();
              }}
              pl="8px"
            >
              Yes, Remove
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
      <Heading>Events Team Members</Heading>
      <TableContainer pt="16px">
        <Table variant="simple">
          <TableCaption>
            Points are updated at the end of the month
          </TableCaption>
          <Thead>
            <Tr>
              <Th>Discord ID</Th>
              <Th>Name</Th>
              <Th>Roblox ID</Th>
              <Th>Points</Th>
              <Th>Remove</Th>
            </Tr>
          </Thead>
          <Tbody>
            {memberData.map((member) => (
              <Tr>
                <Td>{member.id}</Td>
                <Td>{member.name}</Td>
                <Td>{member.roblox_id}</Td>
                <Td>
                  {isManagement ? (
                    <Link
                      onClick={() => {
                        setModalMember(member.id);
                        onOpen();
                      }}
                    >
                      {member.points}
                    </Link>
                  ) : (
                    member.points
                  )}
                </Td>
                <Td>
                  <Link
                    onClick={() => {
                      setDelMember({ id: member.id, name: member.name });
                      openDelConfirm();
                    }}
                  >
                    Remove
                  </Link>
                </Td>
              </Tr>
            ))}
          </Tbody>
        </Table>
      </TableContainer>
    </Container>
  );
}
