import { Button, Card, Checkbox, Col, Form, Input, InputNumber, Row, Select } from "antd";
import { useCallback, useEffect, useMemo, useState } from "react";
import { fetchFilterData } from "../../utils/RenderTemplate";
import { DeleteFilled } from "@ant-design/icons";
import { useTranslation } from "react-i18next";
import { getOrderOperatorsByType, getWhereOperatorsByType } from "../../utils/graphQLmodifier";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import { generateInternalReflections } from "./report-center-modal-utils";
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component.jsx";

export default function ReportCenterModalFiltersSortersComponent({ form, bodyshop }) {
  return (
    <Form.Item style={{ margin: 0, padding: 0 }} dependencies={["key"]}>
      {() => {
        const key = form.getFieldValue("key");
        return <RenderFilters form={form} templateId={key} bodyshop={bodyshop} />;
      }}
    </Form.Item>
  );
}

/**
 * Filters Section
 * @param filters
 * @param form
 * @param bodyshop
 * @returns {JSX.Element}
 * @constructor
 */
function FiltersSection({ filters, form, bodyshop }) {
  const { t } = useTranslation();

  return (
    <Card type="inner" title={t("reportcenter.labels.advanced_filters_filters")} style={{ marginTop: "10px" }}>
      <Form.List name={["filters"]}>
        {(fields, { add, remove }) => {
          return (
            <div>
              {fields.map((field, index) => (
                <Form.Item key={field.key}>
                  <Row gutter={[16, 16]}>
                    <Col span={10}>
                      <Form.Item
                        key={`${index}field`}
                        label={t("reportcenter.labels.advanced_filters_filter_field")}
                        name={[field.name, "field"]}
                        rules={[
                          {
                            required: true
                            //message: t("general.validation.required"),
                          }
                        ]}
                      >
                        <Select
                          getPopupContainer={(trigger) => trigger.parentNode}
                          onChange={() => {
                            // Clear related Fields
                            form.setFieldValue(["filters", field.name, "value"], null);
                            form.setFieldValue(["filters", field.name, "operator"], null);
                          }}
                          options={filters.map((f) => {
                            return {
                              value: f.name,
                              label: f?.translation
                                ? t(f.translation) === f.translation
                                  ? f.label
                                  : t(f.translation)
                                : f.label
                            };
                          })}
                        />
                      </Form.Item>
                    </Col>
                    <Col span={6}>
                      <Form.Item
                        dependencies={[
                          ["filters", field.name, "field"],
                          ["filters", field.name, "value"]
                        ]}
                      >
                        {() => {
                          const name = form.getFieldValue(["filters", field.name, "field"]);
                          const type = filters.find((f) => f.name === name)?.type;

                          return (
                            <Form.Item
                              key={`${index}operator`}
                              label={t("reportcenter.labels.advanced_filters_filter_operator")}
                              name={[field.name, "operator"]}
                              rules={[
                                {
                                  required: true
                                  //message: t("general.validation.required"),
                                }
                              ]}
                            >
                              <Select
                                getPopupContainer={(trigger) => trigger.parentNode}
                                options={getWhereOperatorsByType(type)}
                                onChange={() => {
                                  // Clear related Fields

                                  form.setFieldValue(["filters", field.name, "value"], undefined);
                                }}
                              />
                            </Form.Item>
                          );
                        }}
                      </Form.Item>
                    </Col>
                    <Col span={6}>
                      <Form.Item
                        dependencies={[
                          ["filters", field.name, "field"],
                          ["filters", field.name, "operator"]
                        ]}
                      >
                        {() => {
                          // Because it looks cleaner than inlining.
                          const name = form.getFieldValue(["filters", field.name, "field"]);
                          const type = filters.find((f) => f.name === name)?.type;
                          const reflector = filters.find((f) => f.name === name)?.reflector;
                          const operator = form.getFieldValue(["filters", field.name, "operator"]);
                          const operatorType = operator
                            ? getWhereOperatorsByType(type).find((o) => o.value === operator)?.type
                            : null;

                          return (
                            <Form.Item
                              key={`${index}value`}
                              label={t("reportcenter.labels.advanced_filters_filter_value")}
                              name={[field.name, "value"]}
                              rules={[
                                {
                                  required: true
                                  //message: t("general.validation.required"),
                                }
                              ]}
                            >
                              {(() => {
                                const generateReflections = (reflector) => {
                                  if (!reflector) return [];

                                  const { name } = reflector;
                                  const path = name?.split(".");
                                  const upperPath = path?.[0];
                                  const finalPath = path?.slice(1).join(".");

                                  return generateInternalReflections({
                                    bodyshop,
                                    upperPath,
                                    finalPath,
                                    t
                                  });
                                };

                                const reflections = reflector ? generateReflections(reflector) : [];
                                const fieldPath = [[field.name, "value"]];
                                // We have reflections so we will use a select box
                                if (reflections.length > 0) {
                                  // We have reflections and the operator type is array, so we will use a select box with multiple options
                                  if (operatorType === "array") {
                                    return (
                                      <Select
                                        disabled={!operator}
                                        mode="multiple"
                                        options={reflections}
                                        getPopupContainer={(trigger) => trigger.parentNode}
                                        onChange={(value) => {
                                          form.setFieldValue(fieldPath, value);
                                        }}
                                      />
                                    );
                                  }
                                  return (
                                    <Select
                                      options={reflections}
                                      getPopupContainer={(trigger) => trigger.parentNode}
                                      onChange={(value) => {
                                        form.setFieldValue(fieldPath, value);
                                      }}
                                    />
                                  );
                                }

                                // We have a type of number, so we will use a number input
                                if (type === "number") {
                                  return (
                                    <InputNumber
                                      disabled={!operator}
                                      onChange={(value) => form.setFieldValue(fieldPath, value)}
                                    />
                                  );
                                }

                                // We have a type of date, so we will use a date picker
                                if (type === "date") {
                                  return (
                                    <DateTimePicker
                                      isDateOnly
                                      disabled={!operator}
                                      onChange={(date) => form.setFieldValue(fieldPath, date)}
                                    />
                                  );
                                }

                                // we have a type of boolean, so we will use a select box with a true or false option.
                                if (type === "boolean" || type === "bool") {
                                  return (
                                    <Select
                                      disabled={!operator}
                                      getPopupContainer={(trigger) => trigger.parentNode}
                                      options={[
                                        {
                                          label: t("reportcenter.labels.advanced_filters_true"),
                                          value: true
                                        },
                                        {
                                          label: t("reportcenter.labels.advanced_filters_false"),
                                          value: false
                                        }
                                      ]}
                                      onChange={(value) => form.setFieldValue(fieldPath, value)}
                                    />
                                  );
                                }
                                return (
                                  <Input
                                    disabled={!operator}
                                    onChange={(e) => form.setFieldValue(fieldPath, e.target.value)}
                                  />
                                );
                              })()}
                            </Form.Item>
                          );
                        }}
                      </Form.Item>
                    </Col>
                    <Col span={2}>
                      <DeleteFilled
                        style={{ margin: "1rem", paddingTop: "23px" }}
                        onClick={() => {
                          remove(field.name);
                        }}
                      />
                    </Col>
                  </Row>
                </Form.Item>
              ))}
              <Form.Item>
                <Button
                  type="dashed"
                  onClick={() => {
                    add();
                  }}
                  style={{ width: "100%" }}
                >
                  {t("general.actions.add")}
                </Button>
              </Form.Item>
            </div>
          );
        }}
      </Form.List>
    </Card>
  );
}

/**
 * Sorters Section
 * @param sorters
 * @param form
 * @returns {JSX.Element}
 * @constructor
 */
function SortersSection({ sorters }) {
  const { t } = useTranslation();
  return (
    <Card type="inner" title={t("reportcenter.labels.advanced_filters_sorters")} style={{ marginTop: "10px" }}>
      <Form.List name={["sorters"]}>
        {(fields, { add, remove }) => {
          return (
            <div>
              Sorters
              {fields.map((field, index) => (
                <Form.Item key={field.key}>
                  <Row gutter={[16, 16]}>
                    <Col span={11}>
                      <Form.Item
                        key={`${index}field`}
                        label={t("reportcenter.labels.advanced_filters_sorter_field")}
                        name={[field.name, "field"]}
                        rules={[
                          {
                            required: true
                            //message: t("general.validation.required"),
                          }
                        ]}
                      >
                        <Select
                          options={sorters.map((f) => ({
                            value: f.name,
                            label: f?.translation
                              ? t(f.translation) === f.translation
                                ? f.label
                                : t(f.translation)
                              : f.label
                          }))}
                          getPopupContainer={(trigger) => trigger.parentNode}
                        />
                      </Form.Item>
                    </Col>
                    <Col span={11}>
                      <Form.Item
                        key={`${index}direction`}
                        label={t("reportcenter.labels.advanced_filters_sorter_direction")}
                        name={[field.name, "direction"]}
                        rules={[
                          {
                            required: true
                            //message: t("general.validation.required"),
                          }
                        ]}
                      >
                        <Select
                          options={getOrderOperatorsByType()}
                          getPopupContainer={(trigger) => trigger.parentNode}
                        />
                      </Form.Item>
                    </Col>

                    <Col span={2}>
                      <DeleteFilled
                        style={{ margin: "1rem", paddingTop: "23px" }}
                        onClick={() => {
                          remove(field.name);
                        }}
                      />
                    </Col>
                  </Row>
                </Form.Item>
              ))}
              <Form.Item>
                <Button
                  type="dashed"
                  onClick={() => {
                    add();
                  }}
                  style={{ width: "100%" }}
                >
                  {t("general.actions.add")}
                </Button>
              </Form.Item>
            </div>
          );
        }}
      </Form.List>
    </Card>
  );
}

/**
 * Render Filters
 * @param templateId
 * @param form
 * @param bodyshop
 * @returns {JSX.Element|null}
 * @constructor
 */
function RenderFilters({ templateId, form, bodyshop }) {
  const [state, setState] = useState(null);
  const [visible, setVisible] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const { t } = useTranslation();

  const fetch = useCallback(async () => {
    // Reset all the filters and Sorters.
    form.resetFields(["filters"]);
    form.resetFields(["sorters"]);
    form.resetFields(["defaultSorters"]);

    setIsLoading(true);

    const data = await fetchFilterData({ name: templateId });

    // We have Success
    if (data?.success) {
      if (data?.data?.sorters && data?.data?.sorters.length > 0) {
        const defaultSorters = data?.data?.sorters
          // TODO Why?
          // eslint-disable-next-line no-prototype-builtins
          .filter((sorter) => sorter.hasOwnProperty("default"))
          .map((sorter) => {
            return {
              field: sorter.name,
              direction: sorter.default.direction
            };
          })
          .sort((a, b) => a.default.order - b.default.order);

        form.setFieldValue("defaultSorters", JSON.stringify(defaultSorters));
      }
      // Set the state
      setState(data.data);
    }
    // Something went wrong fetching filter data
    else {
      setState(null);
    }
    setIsLoading(false);
  }, [templateId, form]);

  useEffect(() => {
    if (templateId) {
      fetch();
    }
  }, [templateId, fetch]);

  const filters = useMemo(() => state?.filters || [], [state]);
  const sorters = useMemo(() => state?.sorters || [], [state]);

  if (!templateId) return null;
  if (isLoading) return <LoadingSkeleton />;
  if (!state) return null;

  return (
    <div style={{ marginTop: "10px" }}>
      <Checkbox
        checked={visible}
        onChange={(e) => setVisible(e.target.checked)}
        children={t("reportcenter.labels.advanced_filters")}
      />
      {visible && (
        <div>
          {filters.length > 0 && <FiltersSection filters={filters} form={form} bodyshop={bodyshop} />}
          {sorters.length > 0 && <SortersSection sorters={sorters} form={form} />}
        </div>
      )}
    </div>
  );
}
