/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
  Button,
  LoadingOverlay,
  Modal,
  ModalProps,
  NumberInput,
  Select,
  TextInput,
} from "@mantine/core";
import { useForm, zodResolver } from "@mantine/form";
import _ from "lodash";
import { useEffect, useRef, useState } from "react";
import { z } from "zod";
import { createBid, updateBid } from "../../apis/bid";
import { useConfirmStore } from "../../lib/zustand/use-confirm";
import { IBid, IMetadata } from "../../system/type";
import { formatTimeFromMinutes } from "../../utils";
export interface IBidModelProps extends ModalProps {
  data: IBid | null;
  onUpdated?: () => void;
}

const schema = {
  url: z.string({ message: "Url is required" }).url("Invalid url format"),
  max_price: z
    .number({ message: "Max price is required" })
    .min(1, "Max price must be at least 1"),
  plus_price: z.number().min(0, "Plus price must be at least 1").optional(),
  quantity: z.number().min(1, "Quantity must be at least 1").optional(),
  arrival_offset_seconds_live: z
    .number({ message: "Arrival offset seconds is required" })
    .refine((val) => val >= 60, {
      message: "Arrival offset seconds must be at least 60 seconds (1 minute)",
    })
    .optional(),
  early_tracking_seconds_live: z
    .number({ message: "Early login seconds is required" })
    .refine((val) => val >= 600, {
      message: "Early login seconds must be at least 600 seconds (10 minute)",
    })
    .optional(),
  arrival_offset_seconds_sandbox: z
    .number({ message: "Arrival offset seconds is required" })
    .refine((val) => val >= 60, {
      message: "Arrival offset seconds must be at least 60 seconds (1 minute)",
    })
    .optional(),
  early_tracking_seconds_sandbox: z
    .number({ message: "Early login seconds is required" })
    .refine((val) => val >= 600, {
      message: "Early login seconds must be at least 600 seconds (10 minute)",
    })
    .optional(),
};

export default function BidModal({
  data,
  onUpdated,
  ...props
}: IBidModelProps) {
  const form = useForm({
    validate: zodResolver(z.object(schema)),
  });

  const prevData = useRef<IBid | null>(data);

  const { setConfirm } = useConfirmStore();

  const [loading, setLoading] = useState(false);

  const handleSubmit = async (values: typeof form.values) => {
    if (data) {
      setConfirm({
        title: "Update ?",
        message: `This product will be update`,
        handleOk: async () => {
          setLoading(true);

          const metadata = valuesToMetadata(
            values as IBid & Record<string, any>
          );

          const result = await updateBid({ ...values, metadata });
          setLoading(false);

          if (!result) return;

          props.onClose();

          if (onUpdated) {
            onUpdated();
          }
        },
        okButton: {
          color: "blue",
          value: "Update",
        },
      });
    } else {
      const { url, max_price, plus_price } = values;

      setLoading(true);

      const metadata = valuesToMetadata(values as IBid & Record<string, any>);
      const result = await createBid({
        url,
        max_price,
        plus_price,
        metadata,
      } as IBid);

      setLoading(false);

      if (!result) return;

      props.onClose();

      if (onUpdated) {
        onUpdated();
      }
    }
  };

  const mappingValues = (ignore: string[] = []) => {
    if (!data) return {};
    let values: IBid & Record<string, any> = data;

    const followKey = ["arrival_offset_seconds", "early_tracking_seconds"];

    if (
      data.metadata.length &&
      data.metadata.some((item) => item.key_name === "mode_key")
    ) {
      data.metadata.reduce((prev, cur) => {
        if (ignore.includes(cur.key_name)) {
          prev[cur.key_name as string] = form.values[cur.key_name];

          return prev;
        }

        if (cur.key_name === "mode_key") {
          prev[cur.key_name as string] = cur.value;
          return prev;
        }

        prev[cur.key_name as string] = cur.value;

        return prev;
      }, values);
    } else {
      const metadata = Object.assign(
        { mode_key: "live" },
        ...followKey.map((item) => ({
          [`${item}_live`]: data.web_bid[item as keyof typeof data.web_bid],
          [`${item}_sandbox`]: data.web_bid[item as keyof typeof data.web_bid],
        }))
      );

      values = { ...values, ...metadata };
    }

    return values;
  };

  const valuesToMetadata = (values: IBid & Record<string, any>) => {
    const keys = [
      "mode_key",
      "arrival_offset_seconds_live",
      "arrival_offset_seconds_sandbox",
      "early_tracking_seconds_live",
      "early_tracking_seconds_sandbox",
    ];

    if (!values?.metadata) {
      const mode_key = values.mode_key;

      if (!mode_key) return [];

      const newValues = Object.entries(values)
        .map(([key, value]) => {
          if (keys.includes(key)) {
            return {
              key_name: key,
              value,
            } as IMetadata;
          }

          return null;
        })
        .filter((i) => i !== null);

      return newValues;
    }

    if (values.metadata.length <= 0) {
      return keys.map((item) => {
        return {
          key_name: item,
          value: values[item],
        } as IMetadata;
      });
    }

    return values.metadata.map((item) => {
      return {
        ...item,
        value: values[item.key_name],
      };
    });
  };

  useEffect(() => {
    form.reset();
    if (!data) return;

    const values = mappingValues();

    form.setValues(values);

    prevData.current = data;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data]);

  useEffect(() => {
    if (!props.opened) {
      form.reset();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [props.opened]);

  useEffect(() => {
    if (!data && !form.values.mode_key) {
      form.setValues({ mode_key: "live" });
    } else {
      const values = mappingValues(["mode_key"]);
      form.setValues(values);
    }

    prevData.current = data;

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [form.values["mode_key"]]);

  return (
    <Modal
      className="relative"
      classNames={{
        header: "!flex !item-center !justify-center w-full",
      }}
      {...props}
      size={"xl"}
      title={<span className="text-xl font-bold">Bid</span>}
      centered
    >
      <form
        onSubmit={form.onSubmit(handleSubmit)}
        className="grid grid-cols-2 gap-2.5"
      >
        <Select
          className="col-span-2"
          label="Mode"
          data={[
            { label: "Live", value: "live" },
            { label: "Sandbox", value: "sandbox" },
          ]}
          defaultValue="live"
          checkIconPosition="right"
          allowDeselect={false}
          {...form.getInputProps("mode_key")}
        />

        {data && data.name && (
          <TextInput
            className="col-span-2"
            readOnly={!!data}
            size="sm"
            label="Name"
            value={data.name}
          />
        )}
        <TextInput
          className="col-span-2"
          readOnly={!!data}
          size="sm"
          label="Url"
          {...form.getInputProps("url")}
        />
        <NumberInput
          className="col-span-2"
          size="sm"
          label="Max price"
          {...form.getInputProps("max_price")}
        />
        <NumberInput
          size="sm"
          label="Plus price"
          {...form.getInputProps("plus_price")}
        />
        <NumberInput
          size="sm"
          label="Quantity"
          {...form.getInputProps("quantity")}
        />

        <NumberInput
          description="Note: that only integer minutes are accepted."
          className="col-span-1"
          size="sm"
          label={`Arrival offset seconds (${formatTimeFromMinutes(
            form.getValues()[
              `arrival_offset_seconds_${form.getValues()["mode_key"]}`
            ] / 60
          )})`}
          placeholder="msg: 300"
          {...form.getInputProps(
            `arrival_offset_seconds_${form.getValues()["mode_key"]}`
          )}
        />

        <NumberInput
          description="Note: that only integer minutes are accepted."
          className="col-span-1"
          size="sm"
          label={`Early tracking seconds (${formatTimeFromMinutes(
            form.getValues()[
              `early_tracking_seconds_${form.getValues()["mode_key"]}`
            ] / 60
          )})`}
          placeholder="msg: 600"
          {...form.getInputProps(
            `early_tracking_seconds_${form.getValues()["mode_key"]}`
          )}
        />

        <Button
          //   disabled={_.isEqual(form.values, prevData.current)}
          className="col-span-2"
          type="submit"
          fullWidth
          size="sm"
          mt="md"
        >
          {data ? "Update" : "Create"}
        </Button>
      </form>

      <LoadingOverlay
        visible={loading}
        zIndex={1000}
        overlayProps={{ blur: 2 }}
      />
    </Modal>
  );
}
