import {
  Button,
  Input,
  Link,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  Radio,
  RadioGroup,
  Table,
  TableContainer,
  Tbody,
  Text,
  Td,
  Th,
  Thead,
  Tr,
  VStack,
  useToast,
} from "@chakra-ui/react";
import { useState } from "react";

export default function (props: { isOpen: boolean; onClose: () => void }) {
  const actionMap: { [k: string]: number } = {};
  const [rows, setRows] = useState([] as JSX.Element[]);
  const toast = useToast();
  const fileTypes: { [k: string]: string } = {
    gif: "image/gif",
    heic: "image/heic",
    heif: "image/heif",
    jfif: "image/jpeg",
    jpeg: "image/jpeg",
    jpg: "image/jpg",
    m4v: "video/x-m4v",
    mkv: "video/x-matroska",
    mov: "video/quicktime",
    mp4: "video/mp4",
    png: "image/png",
    webp: "image/webp",
    webm: "video/webm",
    wmv: "video/x-ms-wmv",
  };

  function addUser(user: string) {
    const newRows = [...rows];
    newRows.push(
      <Tr key={user}>
        <Td>{user}</Td>
        <Td>
          <RadioGroup
            onChange={(val) =>
              Object.defineProperty(actionMap, user, {
                value: parseInt(val),
              })
            }
          >
            <VStack>
              <Radio value="0">Do Nothing</Radio>
              <Radio value="1">Hide from Leaderboards</Radio>
              <Radio value="2">Ban</Radio>
            </VStack>
          </RadioGroup>
        </Td>
        <Td>
          <Link onClick={() => removeUser(user)}>Remove</Link>
        </Td>
      </Tr>,
    );

    setRows(newRows);
  }

  function removeUser(user: string) {
    const newRows = [...rows];
    const el = newRows.find((el) => el.key === user);

    if (!el) return;

    const elIdx = newRows.indexOf(el);

    if (elIdx === -1) return;

    newRows.splice(elIdx, 1);
    setRows(newRows);

    delete actionMap[user];
  }

  function reset() {
    (document.getElementById("username") as HTMLInputElement).value = "";
    (document.getElementById("evidence") as HTMLInputElement).value = "";

    setRows([]);
    Object.keys(actionMap).forEach((k) => delete actionMap[k]);

    props.onClose();
  }

  async function submit() {
    const actions: number[] = [];
    const usernames: string[] = [];

    for (const [u, a] of Object.entries(actionMap)) {
      actions.push(a);
      usernames.push(u);
    }

    if (!usernames.length || !actions.length) return;

    const files = (document.getElementById("evidence") as HTMLInputElement)
      .files;

    if (!files) return;

    const [evidence] = files;

    const submitReq = await fetch("/api/reports/submit", {
      body: JSON.stringify({
        actions,
        bypass: true,
        filename: evidence.name,
        filesize: evidence.size,
        usernames,
      }),
      headers: {
        "content-type": "application/json",
      },
      method: "POST",
    });

    if (!submitReq.ok) {
      toast({
        description: ((await submitReq.json()) as { error: string }).error,
        status: "error",
        title: "Failed to submit report",
      });

      return;
    }

    const { id, upload_url }: { [k: string]: string } = await submitReq.json();

    const fileUpload = await fetch(upload_url, {
      body: evidence,
      headers: {
        "content-type":
          evidence.type ||
          fileTypes[
            evidence.name.split(".")[evidence.name.split(".").length - 1]
          ],
      },
      method: "PUT",
    });

    if (!fileUpload.ok) {
      await fetch("/api/reports/recall", {
        body: JSON.stringify({ id }),
        headers: {
          "content-type": "application/json",
        },
        method: "POST",
      });

      toast({
        description: "Failed to upload file",
        status: "error",
        title: "Error",
      });

      return;
    }

    await fetch("/api/reports/complete", {
      body: JSON.stringify({ id }),
      headers: {
        "content-type": "application/json",
      },
      method: "POST",
    });

    toast({
      description: "User moderated",
      status: "success",
      title: "Success",
    });
  }

  return (
    <Modal isCentered isOpen={props.isOpen} onClose={props.onClose}>
      <ModalOverlay />
      <ModalContent>
        <ModalHeader>New Game Ban</ModalHeader>
        <ModalCloseButton />
        <ModalBody>
          <Text>Username(s)</Text>
          <Input id="username" mb="8px" placeholder="builderman" />
          <Button
            onClick={function () {
              const user = (
                document.getElementById("username") as HTMLInputElement
              ).value;

              if (
                !user ||
                user.length < 3 ||
                user.length > 20 ||
                // @ts-expect-error
                user.match(/_/g)?.length > 1 ||
                user.match(/\W/)
              ) {
                toast({
                  description: "Check the username and try again",
                  duration: 5000,
                  isClosable: true,
                  status: "error",
                  title: "Invalid Username",
                });
                return;
              }

              addUser(user);
            }}
          >
            Add
          </Button>
          <br />
          <br />
          <TableContainer>
            <Table variant="simple">
              <Thead>
                <Tr>
                  <Th>Username</Th>
                  <Th>Punishment</Th>
                  <Th>Remove</Th>
                </Tr>
              </Thead>
              <Tbody>{rows}</Tbody>
            </Table>
          </TableContainer>
          <br />
          <br />
          <Text>Evidence</Text>
          <Button
            mr="8px"
            onClick={() => document.getElementById("evidence")?.click()}
          >
            Select Files
          </Button>
          <input id="evidence" type="file" />
        </ModalBody>
      </ModalContent>
      <ModalFooter>
        <Button onClick={reset}>Cancel</Button>
        <Button
          colorScheme="blue"
          disabled={
            !(
              Object.entries(actionMap).length &&
              (document.getElementById("evidence") as HTMLInputElement).files
                ?.length
            )
          }
          ml="8px"
          onClick={async () => await submit()}
        >
          Submit
        </Button>
      </ModalFooter>
    </Modal>
  );
}