import { HolderOutlined, SyncOutlined } from "@ant-design/icons";
import { PageHeader } from "@ant-design/pro-layout";
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
import { Button, Dropdown, Input, Space, Statistic, Table } from "antd";
import _ from "lodash";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { closestCenter, DndContext, DragOverlay, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
import { arrayMove, horizontalListSortingStrategy, SortableContext, useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { restrictToHorizontalAxis } from "@dnd-kit/modifiers";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import { selectDarkMode } from "../../redux/application/application.selectors.js";
import Prompt from "../../utils/prompt.js";
import AlertComponent from "../alert/alert.component.jsx";
import ProductionListColumnsAdd from "../production-list-columns/production-list-columns.add.component";
import ProductionListColumns from "../production-list-columns/production-list-columns.data";
import ProductionListDetail from "../production-list-detail/production-list-detail.component";
import { ProductionListConfigManager } from "./production-list-config-manager.component.jsx";
import ProductionListPrint from "./production-list-print.component";
import ResizeableTitle from "./production-list-table.resizeable.component";
import { logImEXEvent } from "../../firebase/firebase.utils.js";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop,
  technician: selectTechnician,
  currentUser: selectCurrentUser,
  isDarkMode: selectDarkMode
});

// Draggable header cell component - combines drag and resize
function DraggableHeaderCell(props) {
  const { children, columnKey, onResize, width, ...restProps } = props;
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
    id: columnKey,
    disabled: !columnKey
  });

  const style = {
    ...restProps.style,
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.3 : 1,
    userSelect: "none",
    textAlign: "left"
  };

  // If no columnKey, render as regular header
  if (!columnKey) {
    return <ResizeableTitle {...props} />;
  }

  // Only apply drag listeners to elements with data-drag-handle attribute
  const filteredListeners = listeners
    ? {
        onPointerDown: (e) => {
          // Only trigger drag if clicking on the drag handle
          if (e.target.closest('[data-drag-handle="true"]')) {
            listeners.onPointerDown?.(e);
          }
        }
      }
    : {};

  // Combine drag functionality with resize
  return (
    <ResizeableTitle
      {...restProps}
      ref={setNodeRef}
      style={style}
      onResize={onResize}
      width={width}
      dragAttributes={attributes}
      dragListeners={filteredListeners}
    >
      {children}
    </ResizeableTitle>
  );
}

export function ProductionListTable({ loading, data, refetch, bodyshop, technician, currentUser, isDarkMode }) {
  const [searchText, setSearchText] = useState("");
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);

  // NEW: smoother resize
  const [isResizing, setIsResizing] = useState(false);
  const resizeRafRef = useRef(null);
  const pendingResizeRef = useRef(null);

  const [activeId, setActiveId] = useState(null);

  const MIN_COL_WIDTH = 20;

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 1
      }
    })
  );

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

  const assoc = bodyshop.associations.find((a) => a.useremail === currentUser.email);
  const defaultView = assoc?.default_prod_list_view;

  const initialStateRef = useRef(
    (bodyshop.production_config &&
      bodyshop.production_config.find((p) => p.name === defaultView)?.columns.tableState) ||
      (bodyshop.production_config && bodyshop.production_config[0]?.columns.tableState) || {
        sortedInfo: {},
        filteredInfo: { text: "" }
      }
  );

  const initialColumnsRef = useRef(
    (initialStateRef.current &&
      bodyshop?.production_config
        ?.find((p) => p.name === defaultView)
        ?.columns.columnKeys.map((k) => {
          return {
            ...ProductionListColumns({
              bodyshop,
              refetch,
              technician,
              state: initialStateRef.current,
              data,
              activeStatuses: bodyshop.md_ro_statuses.active_statuses,
              treatments: { Production_List_Status_Colors, Enhanced_Payroll }
            }).find((e) => e.key === k.key),
            width: k.width ?? 100
          };
        })) ||
      []
  );

  const [state, setState] = useState(initialStateRef.current);
  const [columns, setColumns] = useState(initialColumnsRef.current);

  const scrollX = useMemo(() => {
    // keep scroll width aligned with the actual column widths so AntD doesn't clamp at a fixed floor
    const sum = columns.reduce((acc, c) => acc + (c.width ?? 100), 0);
    return Math.max(sum, 1);
  }, [columns]);

  const { t } = useTranslation();

  const matchingColumnConfig = useMemo(() => {
    return bodyshop?.production_config?.find((p) => p.name === defaultView);
  }, [bodyshop.production_config, defaultView]);

  // NEW: cleanup RAF on unmount
  useEffect(() => {
    return () => {
      if (resizeRafRef.current) cancelAnimationFrame(resizeRafRef.current);
    };
  }, []);

  useEffect(() => {
    // NEW: while resizing, don’t regenerate columns
    if (isResizing) return;

    // NEW: bail early BEFORE expensive ProductionListColumns(...) call
    if (!_.isEqual(initialColumnsRef.current, columns)) return;

    const newColumns =
      matchingColumnConfig?.columns.columnKeys.map((k) => {
        return {
          ...ProductionListColumns({
            bodyshop,
            technician,
            refetch,
            state,
            data: data,
            activeStatuses: bodyshop.md_ro_statuses.active_statuses,
            treatments: { Production_List_Status_Colors, Enhanced_Payroll }
          }).find((e) => e.key === k.key),
          width: k.width ?? 100
        };
      }) || [];

    setColumns(newColumns);
  }, [
    matchingColumnConfig,
    bodyshop,
    technician,
    data,
    Enhanced_Payroll,
    Production_List_Status_Colors,
    refetch,
    state,
    columns,
    isResizing
  ]);

  const handleTableChange = (pagination, filters, sorter) => {
    const newState = {
      ...state,
      filteredInfo: filters,
      sortedInfo: { columnKey: sorter.columnKey, order: sorter.order }
    };
    if (!_.isEqual(newState, state)) {
      setState(newState);
      setHasUnsavedChanges(true);
    }
    logImEXEvent("production_list_sort_filter", { pagination, filters, sorter });
  };

  const onDragStart = ({ active }) => {
    setActiveId(active.id);
  };

  const onDragEnd = ({ active, over }) => {
    setActiveId(null);
    if (!over || active.id === over.id) return;

    const oldIndex = columns.findIndex((col) => col.key === active.id);
    const newIndex = columns.findIndex((col) => col.key === over.id);

    if (oldIndex !== -1 && newIndex !== -1) {
      const newColumns = arrayMove(columns, oldIndex, newIndex);
      if (!_.isEqual(newColumns, columns)) {
        setColumns(newColumns);
        setHasUnsavedChanges(true);
      }
    }
  };

  const onDragCancel = () => {
    setActiveId(null);
  };

  const removeColumn = (e) => {
    const { key } = e;
    const newColumns = columns.filter((i) => i.key !== key);
    if (!_.isEqual(newColumns, columns)) {
      setColumns(newColumns);
      setHasUnsavedChanges(true);
    }
    logImEXEvent("production_list_remove_column", { key });
  };

  // NEW: commit widths via rAF (less jank)
  const applyColumnWidth = useCallback((columnKey, width) => {
    const nextWidth = Math.max(MIN_COL_WIDTH, Math.round(width));
    setColumns((prev) => {
      const idx = prev.findIndex((c) => c.key === columnKey);
      if (idx === -1) return prev;

      const currentWidth = prev[idx].width ?? 100;
      if (currentWidth === nextWidth) return prev;

      const next = prev.slice();
      next[idx] = { ...next[idx], width: nextWidth };
      return next;
    });
  }, []);

  const handleResize = useCallback(
    (columnKey) =>
      (e, { size }) => {
        pendingResizeRef.current = { columnKey, width: size.width };

        if (resizeRafRef.current) return;
        resizeRafRef.current = requestAnimationFrame(() => {
          resizeRafRef.current = null;
          const pending = pendingResizeRef.current;
          if (!pending) return;
          applyColumnWidth(pending.columnKey, pending.width);
        });
      },
    [applyColumnWidth]
  );

  const handleResizeStart = useCallback(() => {
    setIsResizing(true);
  }, []);

  const handleResizeStop = useCallback(
    (columnKey) =>
      (e, { size }) => {
        setIsResizing(false);

        // Ensure final width is committed
        applyColumnWidth(columnKey, size.width);

        setHasUnsavedChanges(true);
        logImEXEvent("production_list_resize_column", { key: columnKey, width: size.width });
      },
    [applyColumnWidth]
  );

  const addColumn = (newColumn) => {
    const updatedColumns = [...columns, newColumn];
    if (!_.isEqual(updatedColumns, columns)) {
      setColumns(updatedColumns);
      setHasUnsavedChanges(true);
    }
    logImEXEvent("production_list_add_column", { key: newColumn.key });
  };

  const headerItem = (col) => {
    const menu = { onClick: removeColumn, items: [{ key: col.key, label: t("production.actions.removecolumn") }] };

    return (
      <div
        style={{
          display: "flex",
          alignItems: "left",
          width: "100%",
          userSelect: "none",
          minWidth: 0 // critical: allow the flex row to shrink
        }}
      >
        <span
          className="drag-handle-trigger"
          data-drag-handle="true"
          style={{
            marginRight: 8,
            color: "#999",
            cursor: "grab",
            padding: 4,
            display: "inline-flex",
            alignItems: "left",
            userSelect: "none",
            flex: "0 0 auto"
          }}
          title="Drag to reorder column"
        >
          <HolderOutlined />
        </span>

        <Dropdown className="prod-header-dropdown" menu={menu} trigger={["contextMenu"]}>
          <span
            style={{
              flex: "1 1 auto",
              minWidth: 0, // critical: allow text to shrink
              overflow: "hidden", // clip
              textOverflow: "ellipsis", // show …
              whiteSpace: "nowrap", // keep single line
              cursor: "default",
              userSelect: "none",
              display: "block"
            }}
          >
            {col.title}
          </span>
        </Dropdown>
      </div>
    );
  };

  const resetChanges = () => {
    setState(initialStateRef.current);
    setColumns(initialColumnsRef.current);
    setHasUnsavedChanges(false);
  };

  const filterData = (item, searchText) => {
    const fieldsToSearch = [
      item.ro_number,
      item.ownr_co_nm,
      item.ownr_fn,
      item.ownr_ln,
      item.status,
      item.ins_co_nm,
      item.clm_no,
      item.v_model_desc,
      item.v_make_desc
    ];
    return fieldsToSearch.some((field) => (field || "").toString().toLowerCase().includes(searchText.toLowerCase()));
  };

  const dataSource = searchText === "" ? data : data.filter((j) => filterData(j, searchText));

  if (!columns) return <div>No columns found.</div>;

  const totalHrs = data
    .reduce(
      (acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0),
      0
    )
    .toFixed(1);
  const totalLAB = data.reduce((acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1);
  const totalLAR = data.reduce((acc, val) => acc + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1);

  return (
    <div>
      <Prompt when={hasUnsavedChanges} beforeUnload={true} message={t("general.messages.unsavedchangespopup")} />
      {hasUnsavedChanges && (
        <AlertComponent
          type="warning"
          title={
            <div>
              <span>{t("general.messages.unsavedchanges")} </span>
              <span
                onClick={resetChanges}
                style={{
                  cursor: "pointer",
                  textDecoration: "underline",
                  color: "var(--reset-link-color)"
                }}
              >
                {t("general.actions.reset")}
              </span>
            </div>
          }
        />
      )}
      <PageHeader
        title={
          <Space>
            <Statistic title={t("dashboard.titles.productionhours")} value={totalHrs} />
            <Statistic title={t("dashboard.titles.labhours")} value={totalLAB} />
            <Statistic title={t("dashboard.titles.larhours")} value={totalLAR} />
            <Statistic title={t("appointments.labels.inproduction")} value={dataSource?.length} />
          </Space>
        }
        extra={
          <Space wrap>
            <Button
              onClick={() => {
                refetch && refetch();
              }}
              icon={<SyncOutlined />}
            />
            <ProductionListColumnsAdd
              columnState={[columns, setColumns]}
              tableState={state}
              data={data}
              onColumnAdd={addColumn}
            />
            <ProductionListConfigManager
              columns={columns}
              setColumns={setColumns}
              state={state}
              setState={setState}
              refetch={refetch}
              data={data}
              bodyshop={bodyshop}
              technician={technician}
              currentUser={currentUser}
              setHasUnsavedChanges={setHasUnsavedChanges}
              hasUnsavedChanges={hasUnsavedChanges}
              onSave={() => {
                setHasUnsavedChanges(false);
                initialStateRef.current = state;

                // NEW: after saving, treat current columns as the baseline
                initialColumnsRef.current = columns;
              }}
            />
            <Input
              onChange={(e) => setSearchText(e.target.value)}
              placeholder={t("general.labels.search")}
              value={searchText}
            />
            <ProductionListPrint />
          </Space>
        }
      />
      <ProductionListDetail jobs={dataSource} />
      <DndContext
        sensors={sensors}
        onDragStart={onDragStart}
        onDragEnd={onDragEnd}
        onDragCancel={onDragCancel}
        collisionDetection={closestCenter}
        modifiers={[restrictToHorizontalAxis]}
      >
        <SortableContext items={columns.map((col) => col.key)} strategy={horizontalListSortingStrategy}>
          <Table
            sticky
            tableLayout="fixed"
            className="prod-list-table"
            pagination={false}
            size="small"
            {...(Production_List_Status_Colors.treatment === "on" &&
              !isResizing && {
                onRow: (record, index) => {
                  if (!bodyshop.md_ro_statuses.production_colors) return null;
                  const color = bodyshop.md_ro_statuses.production_colors.find((x) => x.status === record.status);
                  if (!color) {
                    if (index % 2 === 0)
                      return {
                        style: {
                          backgroundColor: "var(--table-row-even-bg)"
                        }
                      };
                    return null;
                  }
                  return {
                    className: "rowWithColor",
                    style: {
                      "--bgColor": color.color
                        ? `rgba(${color.color.r},${color.color.g},${color.color.b},${color.color.a || 1})`
                        : "var(--status-row-bg-fallback)"
                    }
                  };
                }
              })}
            components={{
              header: {
                cell: DraggableHeaderCell
              }
            }}
            columns={columns.map((c) => {
              return {
                ...c,
                filteredValue: state.filteredInfo[c.key] || null,
                sortOrder: state.sortedInfo.columnKey === c.key && state.sortedInfo.order,
                title: headerItem(c),
                ellipsis: true,
                width: c.width ?? 100,
                onHeaderCell: (column) => ({
                  columnKey: column.key,
                  width: column.width,
                  onResize: handleResize(column.key),
                  onResizeStart: handleResizeStart,
                  onResizeStop: handleResizeStop(column.key)
                })
              };
            })}
            rowKey="id"
            loading={loading}
            dataSource={dataSource}
            scroll={{ x: scrollX }}
            onChange={handleTableChange}
          />
        </SortableContext>

        <DragOverlay dropAnimation={null}>
          {activeId ? (
            <div
              style={{
                backgroundColor: isDarkMode ? "#141414" : "white",
                color: isDarkMode ? "white" : "#000",
                border: `2px solid ${isDarkMode ? "#177ddc" : "#1890ff"}`,
                borderRadius: "4px",
                padding: "12px 16px",
                boxShadow: "0 4px 12px rgba(0, 0, 0, 0.25)",
                cursor: "grabbing",
                display: "flex",
                alignItems: "center",
                fontWeight: 500,
                minWidth: "120px"
              }}
            >
              <HolderOutlined style={{ marginRight: "8px", color: isDarkMode ? "white" : "#000", fontSize: "16px" }} />
              <span>
                {(() => {
                  const col = columns.find((c) => c.key === activeId);
                  const title = typeof col?.title === "string" ? col.title : col?.dataIndex || col?.key || "Column";
                  return title;
                })()}
              </span>
            </div>
          ) : null}
        </DragOverlay>
      </DndContext>
    </div>
  );
}

export default connect(mapStateToProps, null)(ProductionListTable);
