import { CloseOutlined, DeleteFilled, HolderOutlined } from "@ant-design/icons";
import { closestCenter, DndContext, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
import { arrayMove, rectSortingStrategy, SortableContext, useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Button, Form, Select, Space } from "antd";
import { ChromePicker } from "react-color";
import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
import { getFormListItemTitle } from "../form-list-move-arrows/form-list-item-title.utils";
import ConfigListEmptyState from "../layout-form-row/config-list-empty-state.component.jsx";
import InlineValidatedFormRow from "../layout-form-row/inline-validated-form-row.component.jsx";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import { DEFAULT_TRANSLUCENT_CARD_COLOR, getTintedCardSurfaceStyles } from "./shop-info.color.utils";

import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { useTreatmentsWithConfig } from "../../feature-flags/splitio-react-replacement";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop
});

const mapDispatchToProps = () => ({
  //setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoROStatusComponent);

const SelectorDiv = styled.div`
  .ant-form-item .ant-select {
    width: 200px;
  }

  .production-status-color-title-select {
    min-width: 160px;
    width: 100%;
  }

  .production-status-color-title-select .ant-select-selector {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    padding-inline: 0 !important;
  }

  .production-status-color-title-select .ant-select-selection-item,
  .production-status-color-title-select .ant-select-selection-placeholder {
    font-weight: 500;
  }

  .job-statuses-source-select .ant-select-selector {
    align-items: flex-start !important;
  }

  .job-statuses-source-select .ant-select-selection-wrap {
    gap: 4px 0;
  }

  .job-statuses-source-tag-wrapper {
    display: inline-flex;
    max-width: 100%;
    margin-inline-end: 6px;
    touch-action: none;
  }

  .job-statuses-source-tag-wrapper .ant-select-selection-item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 30px;
    min-width: 132px;
    max-width: 100%;
    padding-inline: 10px;
    border-radius: 999px;
    border: 1px solid var(--ant-color-border);
    background: var(--ant-color-fill-quaternary);
    justify-content: space-between;
    max-width: 100%;
    cursor: grab;
    margin-inline-end: 0;
    user-select: none;
  }

  .job-statuses-source-tag-wrapper .job-statuses-source-tag-handle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--ant-color-text-tertiary);
    flex: none;
    font-size: 12px;
  }

  .job-statuses-source-tag-wrapper .ant-select-selection-item-content {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .job-statuses-source-tag-wrapper .ant-select-selection-item:active {
    cursor: grabbing;
  }

  .job-statuses-source-tag-wrapper .ant-select-selection-item-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 18px;
    height: 18px;
    border-radius: 999px;
    color: var(--ant-color-text-tertiary);
    transition:
      background 0.2s ease,
      color 0.2s ease;
  }

  .job-statuses-source-tag-wrapper .ant-select-selection-item-remove:hover {
    background: var(--ant-color-fill-secondary);
    color: var(--ant-color-text);
  }

  .job-statuses-source-tag-wrapper--dragging {
    opacity: 0.55;
  }
`;

const normalizeStatuses = (statuses) => [...new Set((statuses || []).map((item) => item?.trim()).filter(Boolean))];

const getTranslatedDragRect = (active, delta) => {
  const rect = active?.rect?.current?.initial || active?.rect?.current?.translated;

  if (!rect) return null;

  const x = delta?.x || 0;
  const y = delta?.y || 0;

  return {
    left: rect.left + x,
    right: rect.right + x,
    top: rect.top + y,
    bottom: rect.bottom + y,
    width: rect.width,
    height: rect.height
  };
};

const isPointWithinRect = (point, rect) => {
  if (!point || !rect) return false;

  return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom;
};

const DraggableStatusTag = ({ label, value, closable, onClose }) => {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
    id: value
  });
  const labelText = String(label ?? value);

  return (
    <span
      ref={setNodeRef}
      className={`job-statuses-source-tag-wrapper ${isDragging ? "job-statuses-source-tag-wrapper--dragging" : ""}`}
      data-status-tag-value={value}
      style={{ transform: CSS.Transform.toString(transform), transition }}
      onMouseDown={(event) => {
        event.stopPropagation();
      }}
      onClick={(event) => {
        event.stopPropagation();
      }}
      {...attributes}
      {...listeners}
    >
      <span
        className="ant-select-selection-item"
        onMouseDown={(event) => {
          if (event.target.closest(".ant-select-selection-item-remove")) {
            event.stopPropagation();
            return;
          }

          event.preventDefault();
          event.stopPropagation();
        }}
        onClick={(event) => {
          if (event.target.closest(".ant-select-selection-item-remove")) {
            event.stopPropagation();
            return;
          }

          event.stopPropagation();
        }}
        title={labelText}
      >
        <span className="job-statuses-source-tag-handle" aria-hidden>
          <HolderOutlined />
        </span>
        <span className="ant-select-selection-item-content">{labelText}</span>
        {closable ? (
          <span
            className="ant-select-selection-item-remove"
            onClick={(event) => {
              event.stopPropagation();
              onClose?.(event);
            }}
            onMouseDown={(event) => {
              event.stopPropagation();
            }}
          >
            <CloseOutlined />
          </span>
        ) : null}
      </span>
    </span>
  );
};

const SortableStatusesSelect = ({ value, onChange, mode = "tags", options = [] }) => {
  const statuses = normalizeStatuses(value);
  const isTagsMode = mode === "tags";
  const [knownStatuses, setKnownStatuses] = useState(statuses);
  const selectWrapperRef = useRef(null);
  const dragRectRef = useRef(null);
  const tagSensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 6
      }
    })
  );

  const handleStatusesChange = (nextValues) => {
    const normalizedNextValues = normalizeStatuses(nextValues);
    if (isTagsMode) {
      setKnownStatuses((currentKnownStatuses) => normalizeStatuses([...currentKnownStatuses, ...normalizedNextValues]));
    }
    onChange?.(normalizedNextValues);
  };

  useEffect(() => {
    if (isTagsMode) {
      setKnownStatuses((currentKnownStatuses) => normalizeStatuses([...currentKnownStatuses, ...statuses]));
    }
  }, [isTagsMode, statuses]);

  const shouldMoveStatusToEnd = (activeId, dragRect) => {
    const selectRect =
      selectWrapperRef.current?.querySelector?.(".ant-select-selector")?.getBoundingClientRect?.() ||
      selectWrapperRef.current?.getBoundingClientRect?.();
    if (!dragRect || !selectRect) return false;

    const dragLeadingPoint = {
      x: dragRect.left,
      y: dragRect.top
    };
    const dragTrailingPoint = {
      x: dragRect.right,
      y: dragRect.bottom
    };

    if (!isPointWithinRect(dragLeadingPoint, selectRect) && !isPointWithinRect(dragTrailingPoint, selectRect)) {
      return false;
    }

    const trailingStatus = statuses.filter((status) => status !== activeId).at(-1);
    if (!trailingStatus) return false;

    const trailingTagNode = selectWrapperRef.current?.querySelector?.(
      `.job-statuses-source-tag-wrapper[data-status-tag-value="${CSS.escape(String(trailingStatus))}"]`
    );
    const trailingTagRect = trailingTagNode?.getBoundingClientRect?.();

    if (!trailingTagRect) return false;

    const isOnTrailingRow = dragRect.bottom >= trailingTagRect.top && dragRect.top <= trailingTagRect.bottom;
    if (isOnTrailingRow) {
      return dragRect.left >= trailingTagRect.right - 4;
    }

    return dragRect.top >= trailingTagRect.bottom - 4;
  };

  const handleStatusSortEnd = ({ active, over, delta }) => {
    const oldIndex = statuses.indexOf(active.id);
    const dragRect = dragRectRef.current || getTranslatedDragRect(active, delta);
    dragRectRef.current = null;

    if (oldIndex < 0) return;

    if (!over) {
      if (oldIndex !== statuses.length - 1 && shouldMoveStatusToEnd(active.id, dragRect)) {
        onChange?.(arrayMove(statuses, oldIndex, statuses.length - 1));
      }
      return;
    }

    if (active.id === over.id) return;

    const newIndex = statuses.indexOf(over.id);

    if (newIndex < 0) return;

    onChange?.(arrayMove(statuses, oldIndex, newIndex));
  };

  const renderStatusTag = ({ label, value: tagValue, closable, onClose }) => {
    return <DraggableStatusTag closable={closable} label={label} onClose={onClose} value={tagValue} />;
  };

  const statusSelectOptions = isTagsMode
    ? knownStatuses.map((status) => ({
        value: status,
        label: status
      }))
    : options;

  if (statuses.length === 0) {
    return (
      <Select
        className="job-statuses-source-select"
        mode={mode}
        onChange={handleStatusesChange}
        options={statusSelectOptions}
        value={statuses}
      />
    );
  }

  return (
    <div ref={selectWrapperRef}>
      <DndContext
        collisionDetection={closestCenter}
        onDragCancel={() => {
          dragRectRef.current = null;
        }}
        onDragEnd={handleStatusSortEnd}
        onDragMove={({ active, delta }) => {
          dragRectRef.current = getTranslatedDragRect(active, delta);
        }}
        sensors={tagSensors}
      >
        <SortableContext items={statuses} strategy={rectSortingStrategy}>
          <Select
            className="job-statuses-source-select"
            mode={mode}
            onChange={handleStatusesChange}
            options={statusSelectOptions}
            tagRender={renderStatusTag}
            value={statuses}
          />
        </SortableContext>
      </DndContext>
    </div>
  );
};

export function ShopInfoROStatusComponent({ bodyshop, form }) {
  const { t } = useTranslation();
  const allStatuses = normalizeStatuses(Form.useWatch(["md_ro_statuses", "statuses"], form));
  const productionStatuses = Form.useWatch(["md_ro_statuses", "production_statuses"], form) || [];
  const additionalBoardStatuses = Form.useWatch(["md_ro_statuses", "additional_board_statuses"], form) || [];
  const productionColors = Form.useWatch(["md_ro_statuses", "production_colors"], form) || [];
  const statusOptions = allStatuses;
  const statusSelectOptions = statusOptions.map((item) => ({ value: item, label: item }));
  const availableProductionStatuses = [...new Set([...productionStatuses, ...additionalBoardStatuses].filter(Boolean))];

  const {
    treatments: { Production_List_Status_Colors }
  } = useTreatmentsWithConfig({
    attributes: {},
    names: ["Production_List_Status_Colors"],
    splitKey: bodyshop.imexshopid
  });

  return (
    <SelectorDiv id="jobstatus">
      <LayoutFormRow grow header={t("bodyshop.labels.job_status_options")}>
        <div>
          <Form.Item
            name={["md_ro_statuses", "statuses"]}
            label={t("bodyshop.labels.alljobstatuses")}
            required
            rules={[
              {
                validator: async (_, value) => {
                  const populatedStatuses = normalizeStatuses(value);

                  if (populatedStatuses.length === 0) {
                    return Promise.reject(
                      new Error(
                        t("general.validation.required", {
                          label: t("bodyshop.labels.alljobstatuses")
                        })
                      )
                    );
                  }

                  if (populatedStatuses.length !== (value || []).filter(Boolean).length) {
                    return Promise.reject(new Error(t("bodyshop.errors.duplicate_job_status")));
                  }
                }
              }
            ]}
          >
            <SortableStatusesSelect />
          </Form.Item>
          <Form.Item
            name={["md_ro_statuses", "active_statuses"]}
            label={t("bodyshop.fields.statuses.active_statuses")}
            rules={[
              {
                required: true,
                //message: t("general.validation.required"),
                type: "array"
              }
            ]}
          >
            <SortableStatusesSelect mode="multiple" options={statusSelectOptions} />
          </Form.Item>
          <Form.Item
            name={["md_ro_statuses", "pre_production_statuses"]}
            label={t("bodyshop.fields.statuses.pre_production_statuses")}
            rules={[
              {
                required: true,
                //message: t("general.validation.required"),
                type: "array"
              }
            ]}
          >
            <SortableStatusesSelect mode="multiple" options={statusSelectOptions} />
          </Form.Item>
          <Form.Item
            name={["md_ro_statuses", "production_statuses"]}
            label={t("bodyshop.fields.statuses.production_statuses")}
            rules={[
              {
                required: true,
                //message: t("general.validation.required"),
                type: "array"
              }
            ]}
          >
            <SortableStatusesSelect mode="multiple" options={statusSelectOptions} />
          </Form.Item>
          <Form.Item
            name={["md_ro_statuses", "post_production_statuses"]}
            label={t("bodyshop.fields.statuses.post_production_statuses")}
            rules={[
              {
                required: true,
                //message: t("general.validation.required"),
                type: "array"
              }
            ]}
          >
            <SortableStatusesSelect mode="multiple" options={statusSelectOptions} />
          </Form.Item>
          <Form.Item
            name={["md_ro_statuses", "ready_statuses"]}
            label={t("bodyshop.fields.statuses.ready_statuses")}
            rules={[
              {
                //required: true,
                //message: t("general.validation.required"),
                type: "array"
              }
            ]}
          >
            <SortableStatusesSelect mode="multiple" options={statusSelectOptions} />
          </Form.Item>
          <Form.Item
            name={["md_ro_statuses", "additional_board_statuses"]}
            label={t("bodyshop.fields.statuses.additional_board_statuses")}
            rules={[
              {
                //required: true,
                //message: t("general.validation.required"),
                type: "array"
              }
            ]}
          >
            <SortableStatusesSelect mode="multiple" options={statusSelectOptions} />
          </Form.Item>
        </div>
      </LayoutFormRow>
      <LayoutFormRow grow header={t("general.actions.defaults")}>
        <Form.Item
          label={t("bodyshop.fields.statuses.default_scheduled")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
          name={["md_ro_statuses", "default_scheduled"]}
        >
          <Select options={statusSelectOptions} />
        </Form.Item>
        <Form.Item
          label={t("bodyshop.fields.statuses.default_arrived")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
          name={["md_ro_statuses", "default_arrived"]}
        >
          <Select options={statusSelectOptions} />
        </Form.Item>
        <Form.Item
          label={t("bodyshop.fields.statuses.default_exported")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
          name={["md_ro_statuses", "default_exported"]}
        >
          <Select options={statusSelectOptions} />
        </Form.Item>
        <Form.Item
          label={t("bodyshop.fields.statuses.default_imported")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
          name={["md_ro_statuses", "default_imported"]}
        >
          <Select options={statusSelectOptions} />
        </Form.Item>
        <Form.Item
          label={t("bodyshop.fields.statuses.default_invoiced")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
          name={["md_ro_statuses", "default_invoiced"]}
        >
          <Select options={statusSelectOptions} />
        </Form.Item>
        <Form.Item
          label={t("bodyshop.fields.statuses.default_completed")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
          name={["md_ro_statuses", "default_completed"]}
        >
          <Select options={statusSelectOptions} />
        </Form.Item>
        <Form.Item
          label={t("bodyshop.fields.statuses.default_delivered")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
          name={["md_ro_statuses", "default_delivered"]}
        >
          <Select options={statusSelectOptions} />
        </Form.Item>
        <Form.Item
          label={t("bodyshop.fields.statuses.default_void")}
          rules={[
            {
              required: true
              //message: t("general.validation.required"),
            }
          ]}
          name={["md_ro_statuses", "default_void"]}
        >
          <Select options={statusSelectOptions} />
        </Form.Item>
      </LayoutFormRow>
      {Production_List_Status_Colors.treatment === "on" && (
        <Form.List name={["md_ro_statuses", "production_colors"]}>
          {(fields, { add, remove }) => {
            return (
              <LayoutFormRow
                grow
                header={t("bodyshop.fields.statuses.production_colors")}
                id="production_colors"
                actions={[
                  <Button
                    key="add-production-status-color"
                    type="primary"
                    block
                    onClick={() => {
                      add({
                        color: { ...DEFAULT_TRANSLUCENT_CARD_COLOR }
                      });
                    }}
                  >
                    {t("bodyshop.actions.add_production_status_color")}
                  </Button>
                ]}
              >
                <div>
                  {fields.length === 0 ? (
                    <ConfigListEmptyState actionLabel={t("bodyshop.actions.add_production_status_color")} />
                  ) : (
                    <Space size="large" wrap align="start">
                      {fields.map((field, index) => {
                        const productionColor = productionColors[field.name] || {};
                        const productionColorSurfaceStyles = getTintedCardSurfaceStyles(productionColor.color);
                        const selectedProductionColorStatuses = productionColors
                          .map((item) => item?.status)
                          .filter(Boolean);
                        const productionColorStatusOptions = [
                          ...new Set([productionColor.status, ...availableProductionStatuses])
                        ]
                          .filter(Boolean)
                          .filter(
                            (status) =>
                              status === productionColor.status || !selectedProductionColorStatuses.includes(status)
                          );

                        return (
                          <InlineValidatedFormRow
                            form={form}
                            errorNames={[["md_ro_statuses", "production_colors", field.name, "status"]]}
                            key={field.key}
                            noDivider
                            title={
                              <Form.Item
                                noStyle
                                key={`${index}status`}
                                name={[field.name, "status"]}
                                rules={[
                                  {
                                    required: true
                                    //message: t("general.validation.required"),
                                  }
                                ]}
                              >
                                <Select
                                  className="production-status-color-title-select"
                                  variant="borderless"
                                  placeholder={getFormListItemTitle(
                                    t("jobs.fields.status"),
                                    index,
                                    productionColor.status
                                  )}
                                  options={productionColorStatusOptions.map((item) => ({
                                    value: item,
                                    label: item
                                  }))}
                                />
                              </Form.Item>
                            }
                            extra={
                              <Button
                                type="text"
                                danger
                                icon={<DeleteFilled />}
                                onClick={() => {
                                  remove(field.name);
                                }}
                              />
                            }
                            {...productionColorSurfaceStyles}
                            style={{ width: 260, marginBottom: 0 }}
                          >
                            <div>
                              <Form.Item
                                key={`${index}color`}
                                name={[field.name, "color"]}
                                rules={[
                                  {
                                    required: true
                                    //message: t("general.validation.required"),
                                  }
                                ]}
                              >
                                <ColorPicker />
                              </Form.Item>
                            </div>
                          </InlineValidatedFormRow>
                        );
                      })}
                    </Space>
                  )}
                </div>
              </LayoutFormRow>
            );
          }}
        </Form.List>
      )}
    </SelectorDiv>
  );
}

export const ColorPicker = ({ value, onChange, ...restProps }) => {
  const handleChange = (color) => {
    if (onChange) onChange(color.rgb);
  };
  return <ChromePicker {...restProps} color={value} onChangeComplete={handleChange} />;
};
