import {
  Container,
  Paper,
  Input,
  Slider,
  TextInput,
  Button,
  Divider,
  Flex,
  ActionIcon,
} from "@mantine/core";
import { randomId } from "@mantine/hooks";
import { useForm } from "@mantine/form";
import React from "react";
import { Params, useLoaderData, useParams, useNavigate } 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) => (value.length < 1 ? "Please enter a name" : null),
      orders: {
        name: (value) => (value.length < 1 ? "Please enter a name" : null),
        add_ons: {
          name: (value) => (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) {
          navigate(`/dashboard/subs/${username}`);
        } else {
          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 (
    <form onSubmit={handleSubmit}>
      <Container pb="xl">
        <h1>{name}</h1>
        <>
          <TextInput {...form.getInputProps("name")} label="Name" />
          {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>
                <h4>Add-On</h4>
                {form
                  .getValues()
                  .orders[idx].add_ons.map(
                    ({ id: add_on_id, _delete: _add_on_delete }, add_on_idx) =>
                      _add_on_delete ? null : (
                        <Paper key={add_on_id} p="xs">
                          <Flex gap="xl" justify="space-between">
                            <TextInput
                              {...form.getInputProps(
                                `orders.${idx}.add_ons.${add_on_idx}.name`
                              )}
                              label="Name"
                            />
                            <ActionIcon
                              color="red.8"
                              onClick={() => handleRemoveAddOn(idx, add_on_idx)}
                            >
                              <IconMinus />
                            </ActionIcon>
                          </Flex>
                          <Input.Wrapper label="Probability">
                            <Slider
                              {...form.getInputProps(
                                `orders.${idx}.add_ons.${add_on_idx}.probability`
                              )}
                              name="Probability"
                              domain={[0, 1]}
                              step={0.05}
                            />
                          </Input.Wrapper>
                        </Paper>
                      )
                  )}
                <Button onClick={() => handleNewAddOn(idx)}>
                  <IconPlus
                    style={{ width: "60%", height: "60%" }}
                    stroke={2}
                  />
                  New Add On
                </Button>
              </Paper>
            )
          )}
          <Button onClick={handleNewOrder}>
            <IconPlus style={{ width: "60%", height: "60%" }} stroke={2} />
            New Order
          </Button>
          <Divider my="md" />
          <Flex justify="flex-end">
            <Button type="submit">Save</Button>
          </Flex>
        </>
      </Container>
    </form>
  );
};
