import {
  Container,
  Paper,
  Input,
  Slider,
  TextInput,
  Button,
  Flex,
  ActionIcon,
  Title,
  Box,
  Affix,
} from "@mantine/core";
import { notifications } from "@mantine/notifications";
import { randomId } from "@mantine/hooks";
import { useForm } from "@mantine/form";
import React from "react";
import {
  Params,
  useLoaderData,
  useParams,
  useNavigate,
  Link,
} from "react-router";
import { IconMinus, IconPlus } from "@tabler/icons-react";

export const subOrderSetLoader = async ({
  params: { username, set_id },
}: {
  params: Params<string>;
}) =>
  fetch(`/api/subs/${username}/sets/${set_id}`).then((response) =>
    response.json(),
  );

type FormOrderSetOrderAddOn = Omit<OrderSetOrderAddOn, "id"> & {
  id: number | string;
  _delete?: boolean;
};

type FormOrderSetOrder = Omit<OrderSetOrder, "id" | "add_ons"> & {
  id: number | string;
  _delete?: boolean;
  add_ons: FormOrderSetOrderAddOn[];
};

type FormOrderSet = Omit<OrderSet, "orders"> & {
  orders: FormOrderSetOrder[];
};

export const SubOrderSet: React.FC = () => {
  const navigate = useNavigate();
  const { username, set_id } = useParams();
  const { id, name, orders } = useLoaderData<OrderSet>();

  const form = useForm<FormOrderSet>({
    mode: "uncontrolled",
    initialValues: { id, name, orders },
    validate: {
      name: (value: string) =>
        value.length < 1 ? "Please enter a name" : null,
      orders: {
        name: (value: string) =>
          value.length < 1 ? "Please enter a name" : null,
        add_ons: {
          name: (value: string) =>
            value.length < 1 ? "Please enter a name" : null,
        },
      },
    },
  });

  const handleSubmit = React.useCallback(
    form.onSubmit((values) => {
      fetch(`/api/subs/${username}/sets/${set_id}`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(values),
      }).then((response) => {
        if (response.ok) {
          notifications.show({
            title: "Success",
            message: `Updates to ${values.name} were successful`,
            color: "green",
          });
          navigate(`/dashboard/subs/${username}`);
        } else {
          notifications.show({
            title: "Error",
            message: "There was a problem with your request",
            color: "red",
          });
          console.error(response.statusText);
        }
      });
    }),
    [form],
  );

  const handleNewOrder = React.useCallback(() => {
    form.insertListItem("orders", {
      id: `new_${randomId()}`,
      name: "",
      weight: 10,
      repeat: 0.8,
      add_ons: [],
    });
  }, [form]);

  const handleRemoveOrder = React.useCallback(
    (idx: number) => {
      const orderId = form.getValues().orders[idx].id.toString();

      if (orderId.indexOf("new_") === 0) {
        form.removeListItem("orders", idx);
      } else {
        form.setFieldValue(`orders.${idx}._delete`, true);
      }
    },
    [form],
  );

  const handleNewAddOn = React.useCallback(
    (idx: number) => {
      form.insertListItem(`orders.${idx}.add_ons`, {
        id: `new_${randomId()}`,
        name: "",
        probability: 0.5,
      });
    },
    [form],
  );

  const handleRemoveAddOn = React.useCallback(
    (idx: number, add_on_idx: number) => {
      const addOnId = form
        .getValues()
        .orders[idx].add_ons[add_on_idx].id.toString();

      if (addOnId.indexOf("new_") === 0) {
        form.removeListItem(`orders.${idx}.add_ons`, add_on_idx);
      } else {
        form.setFieldValue(`orders.${idx}.add_ons.${add_on_idx}._delete`, true);
      }
    },
    [form],
  );

  return (
    <Container pb="xl">
      <Box mb="lg">
        <Title order={1}>{name}</Title>
        <Link to={`/dashboard/subs/${username}`}>Return to {username}</Link>
      </Box>
      <form id="order-set" onSubmit={handleSubmit}>
        <TextInput {...form.getInputProps("name")} label="Name" />
        <Title order={2} mt="lg" mb="sm">
          Orders
        </Title>
        {form.getValues().orders.map(({ id: order_id, _delete }, idx) =>
          _delete ? null : (
            <Paper key={order_id} bg="gray.2">
              <Flex gap="xl" justify="space-between">
                <TextInput
                  {...form.getInputProps(`orders.${idx}.name`)}
                  label="Name"
                  flex={1}
                />
                <ActionIcon
                  color="red.8"
                  onClick={() => handleRemoveOrder(idx)}
                >
                  <IconMinus />
                </ActionIcon>
              </Flex>
              <Input.Wrapper
                label="Weight"
                description="Chance this order will be selected"
              >
                <Slider
                  {...form.getInputProps(`orders.${idx}.weight`)}
                  domain={[0, 100]}
                />
              </Input.Wrapper>
              <Input.Wrapper
                label="Repeat"
                description="Percent chance that this order will repeat the next day"
              >
                <Slider
                  {...form.getInputProps(`orders.${idx}.repeat`)}
                  domain={[0, 1]}
                  step={0.05}
                />
              </Input.Wrapper>
              <Paper p="xs">
                <Title order={4} mb="sm">
                  Add-Ons
                </Title>
                {form
                  .getValues()
                  .orders[
                    idx
                  ].add_ons.map(({ id: add_on_id, _delete: _add_on_delete }, add_on_idx) =>
                    _add_on_delete ? null : (
                      <Flex
                        key={add_on_id}
                        gap="xl"
                        align="center"
                        justify="space-between"
                      >
                        <TextInput
                          {...form.getInputProps(
                            `orders.${idx}.add_ons.${add_on_idx}.name`,
                          )}
                        />
                        <Input.Wrapper flex={1}>
                          <Slider
                            {...form.getInputProps(
                              `orders.${idx}.add_ons.${add_on_idx}.probability`,
                            )}
                            domain={[0, 1]}
                            step={0.05}
                          />
                        </Input.Wrapper>
                        <ActionIcon
                          color="red.8"
                          mt="-8px"
                          onClick={() => handleRemoveAddOn(idx, add_on_idx)}
                        >
                          <IconMinus />
                        </ActionIcon>
                      </Flex>
                    ),
                  )}
                <Button onClick={() => handleNewAddOn(idx)}>
                  <IconPlus
                    style={{ width: "60%", height: "60%" }}
                    stroke={2}
                  />
                  New Add On
                </Button>
              </Paper>
            </Paper>
          ),
        )}
        <Button onClick={handleNewOrder}>
          <IconPlus style={{ width: "60%", height: "60%" }} stroke={2} />
          New Order
        </Button>
        <Box my="40px" />
        <Affix position={{ bottom: 0 }} w="100%">
          <Paper mb={0} bg="gray.1">
            <Container>
              <Flex justify="flex-end">
                <Button type="submit" form="order-set">
                  Save
                </Button>
              </Flex>
            </Container>
          </Paper>
        </Affix>
      </form>
    </Container>
  );
};
