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

export async function loader({
  context,
  params,
}: {
  context: RequestContext;
  params: LoaderFunctionArgs & { uid: string };
}) {
  const { current_user: user } = context.data;

  if (!user)
    throw new Response(null, {
      status: 401,
    });

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

  const strikeData = await context.env.D1.prepare(
    "SELECT * FROM et_strikes WHERE user = ?;",
  )
    .bind(params.uid)
    .all();

  return {
    can_manage: Boolean([1 << 4, 1 << 12].find((p) => user.permissions & p)),
    strikes: strikeData.results,
    user: params.uid,
  };
}

export default function () {
  const { can_manage, strikes, user } = useLoaderData<typeof loader>();
  const [strikeData, setStrikeData] = useState(strikes);
  const toast = useToast();
  const [rmStrikeId, setRmStrikeId] = useState("");
  const [strikeReason, setStrikeReason] = useState("");

  async function removeStrike(id: string) {
    const removeResp = await fetch(`/api/events-team/strikes/${id}`, {
      method: "DELETE",
    });

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

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

      toast({
        description: msg,
        status: "error",
        title: "Failed to remove strike",
      });

      return;
    }

    toast({
      description: `Strike ${id} was removed`,
      status: "success",
      title: "Strike Removed",
    });

    setStrikeData(strikeData.filter((strike) => strike.id !== id));
    closeRmStrike();
  }

  async function addStrike() {
    const addStrikeResp = await fetch("/api/events-team/strikes/new", {
      body: JSON.stringify({
        reason: strikeReason,
        user,
      }),
      headers: {
        "content-type": "application/json",
      },
      method: "POST",
    });

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

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

      toast({
        description: msg,
        status: "error",
        title: "Failed to add strike",
      });

      return;
    }

    toast({
      description: "Strike added",
      status: "success",
      title: "Success",
    });

    const newStrikeData = strikeData;

    newStrikeData.push(await addStrikeResp.json());
    setStrikeData(newStrikeData);
    closeAddStrike();
  }

  const {
    isOpen: rmStrikeOpen,
    onClose: closeRmStrike,
    onOpen: openRmStrike,
  } = useDisclosure();
  const {
    isOpen: addStrikeOpen,
    onClose: closeAddStrike,
    onOpen: openAddStrike,
  } = useDisclosure();

  return (
    <Container maxW="container.lg">
      <Modal isOpen={rmStrikeOpen} onClose={closeRmStrike}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Remove Strike</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <Text>Are you sure you want to remove this strike?</Text>
          </ModalBody>
          <ModalFooter>
            <Button mr="8px">No</Button>
            <Button
              colorScheme="red"
              onClick={async () => await removeStrike(rmStrikeId)}
            >
              Yes
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
      <Modal isOpen={addStrikeOpen} onClose={closeAddStrike}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Add Strike</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <Heading mb="8px" size="xs">
              Reason
            </Heading>
            <Textarea
              onChange={(e) => setStrikeReason(e.target.value)}
              placeholder="Strike reason"
              value={strikeReason}
            />
          </ModalBody>
          <ModalFooter>
            <Button
              mr="8px"
              onClick={() => {
                closeAddStrike();
                setStrikeReason("");
              }}
            >
              Cancel
            </Button>
            <Button colorScheme="red" onClick={async () => await addStrike()}>
              Add Strike
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
      <Heading my="16px">Strikes</Heading>
      <TableContainer>
        <Table variant="simple">
          <Thead>
            <Tr>
              <Th>Time Added</Th>
              <Th>Added By</Th>
              <Th>Reason</Th>
              <Th>Remove</Th>
            </Tr>
          </Thead>
          <Tbody>
            {strikeData.map((strike: { [k: string]: any }) => (
              <Tr>
                <Td>{new Date(strike.created_at).toUTCString()}</Td>
                <Td>{strike.created_by}</Td>
                <Td>{strike.reason}</Td>
                <Td>
                  {can_manage ? (
                    <Link
                      onClick={() => {
                        setRmStrikeId(strike.id);
                        openRmStrike();
                      }}
                    >
                      Remove
                    </Link>
                  ) : null}
                </Td>
              </Tr>
            ))}
          </Tbody>
        </Table>
      </TableContainer>
      <Link color="#646cff" onClick={openAddStrike} py="16px">
        Add Strike
      </Link>
    </Container>
  );
}