import {
  Button,
  Input,
  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 [users, setUsers] = useState([] as string[]);
  const [loading, setLoading] = useState(false);
  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/mp4",
    mp4: "video/mp4",
    png: "image/png",
    webp: "image/webp",
    webm: "video/webm",
    wmv: "video/x-ms-wmv",
  };

  function addUser(user: string) {
    (document.getElementById("username") as HTMLInputElement).value = "";
    const newUsers = [...users];

    if (newUsers.includes(user)) return;

    newUsers.push(user);
    setUsers(newUsers);
  }

  function removeUser(user: string) {
    const newUsers = [...users];
    const userIdx = newUsers.indexOf(user);

    if (userIdx === -1) return;

    newUsers.splice(userIdx, 1);
    setUsers(newUsers);

    delete actionMap[user];
  }

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

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

    props.onClose();
  }

  async function submit() {
    setLoading(true);
    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) {
      setLoading(false);
      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) {
      setLoading(false);
      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) {
      setLoading(false);
      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",
    });

    setLoading(false);
    props.onClose();
  }

  return (
    <Modal isCentered isOpen={props.isOpen} onClose={props.onClose}>
      <ModalOverlay />
      <ModalContent>
        <ModalHeader>New Game Ban</ModalHeader>
        <ModalCloseButton onClick={reset} />
        <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>&nbsp;</Th>
                </Tr>
              </Thead>
              <Tbody>
                {users.map((user) => (
                  <Tr key={user}>
                    <Td>{user}</Td>
                    <Td>
                      <RadioGroup
                        onChange={(val) => (actionMap[user] = 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>
                      <Button onClick={() => removeUser(user)} variant="ghost">
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          width="16"
                          height="16"
                          fill="currentColor"
                          viewBox="0 0 16 16"
                        >
                          <path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6Z" />
                          <path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1ZM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118ZM2.5 3h11V2h-11v1Z" />
                        </svg>
                      </Button>
                    </Td>
                  </Tr>
                ))}
              </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>
        <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()}
            isLoading={loading}
            loadingText="Submitting..."
          >
            Submit
          </Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  );
}