import { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';

const toLocalCoord = (value, scale) => value / scale;

const getPinnedClipLeft = (container, overlayParent, columnPinning, scale) => {
  const pinnedIds = (columnPinning?.left || []).filter(Boolean);
  if (!pinnedIds.length) return 0;

  const parentRect = overlayParent.getBoundingClientRect();
  let maxRight = 0;

  for (const id of pinnedIds) {
    const el = container.querySelector(`[data-col-select-id="${id}"]`);
    if (!el) continue;
    const rect = el.getBoundingClientRect();
    maxRight = Math.max(maxRight, rect.right - parentRect.left);
  }

  return toLocalCoord(maxRight, scale);
};

const getOverlayRect = (container, overlayParent, selectedColumnId, columnPinning, scale) => {
  const columnEl = container.querySelector(
    `[data-col-select-id="${selectedColumnId}"]`,
  );
  if (!columnEl || !overlayParent) return null;

  const bodyCell = container.querySelector(
    `td[data-col-id="${selectedColumnId}"]`,
  );

  const parentRect = overlayParent.getBoundingClientRect();
  const containerRect = container.getBoundingClientRect();
  const columnRect = columnEl.getBoundingClientRect();
  const alignRect = bodyCell?.getBoundingClientRect() ?? columnRect;

  let top = toLocalCoord(columnRect.top - parentRect.top, scale);
  let left = toLocalCoord(alignRect.left - parentRect.left, scale);
  let width = toLocalCoord(alignRect.width, scale);
  const height = toLocalCoord(containerRect.bottom - columnRect.top, scale);

  const pinnedIds = (columnPinning?.left || []).filter(Boolean);
  const isSelectedPinned = pinnedIds.includes(selectedColumnId);

  if (!isSelectedPinned && pinnedIds.length) {
    const clipLeft = getPinnedClipLeft(container, overlayParent, columnPinning, scale);
    const overlayRight = left + width;
    if (overlayRight <= clipLeft) return null;
    if (left < clipLeft) {
      width = overlayRight - clipLeft;
      left = clipLeft;
    }
  }

  if (width <= 0 || height <= 0) return null;

  return { top, left, width, height };
};

export const ColumnSelectionOverlay = ({
  selectedColumnId,
  containerRef,
  scale = 1,
  columnSizing,
  columnPinning,
  showColumnFilters,
}) => {
  const [rect, setRect] = useState(null);
  const [portalTarget, setPortalTarget] = useState(null);

  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    const overlayParent = container.parentElement;
    setPortalTarget(overlayParent);
  }, [containerRef, selectedColumnId]);

  useEffect(() => {
    const container = containerRef.current;
    const overlayParent = container?.parentElement;
    if (!selectedColumnId || !container || !overlayParent) {
      setRect(null);
      return;
    }

    const updateRect = () => {
      setRect(getOverlayRect(container, overlayParent, selectedColumnId, columnPinning, scale));
    };

    updateRect();

    const scrollTargets = new Set([container]);
    let scrollParent = container.parentElement;
    for (let i = 0; i < 3 && scrollParent; i += 1) {
      scrollTargets.add(scrollParent);
      scrollParent = scrollParent.parentElement;
    }

    scrollTargets.forEach((target) => {
      target.addEventListener('scroll', updateRect, { passive: true });
    });
    window.addEventListener('resize', updateRect);

    const resizeObserver = new ResizeObserver(updateRect);
    resizeObserver.observe(container);
    resizeObserver.observe(overlayParent);

    const header = container.querySelector('.custom-table-header');
    if (header) {
      resizeObserver.observe(header);
    }

    const tableBody = container.querySelector('.MuiTableBody-root');
    if (tableBody) {
      resizeObserver.observe(tableBody);
    }

    return () => {
      scrollTargets.forEach((target) => {
        target.removeEventListener('scroll', updateRect);
      });
      window.removeEventListener('resize', updateRect);
      resizeObserver.disconnect();
    };
  }, [selectedColumnId, containerRef, scale, columnSizing, columnPinning, showColumnFilters]);

  if (!rect || !portalTarget) return null;

  return createPortal(
    <div
      style={{
        position: 'absolute',
        top: rect.top,
        left: rect.left,
        width: rect.width,
        height: rect.height,
        backgroundColor: 'rgba(88, 154, 47, 0.2)',
        border: '1px solid #589A2F',
        boxSizing: 'border-box',
        pointerEvents: 'none',
        zIndex: 1,
      }}
    />,
    portalTarget,
  );
};
