const FORM_SELECTOR = '.el-dialog .el-form';
const ITEM_SELECTOR = '.el-form-item';
const COLUMN_TOLERANCE = 8;
const REQUIRED_MARK_WIDTH = 12;

let textMeasureEl;

const isVisible = element => {
  if (!element) return false;
  const rect = element.getBoundingClientRect();
  return rect.width > 0 && rect.height > 0;
};

const getDirectLabel = item => {
  return Array.from(item.children).find(child => child.classList.contains('el-form-item__label'));
};

const getColumnLeft = item => {
  const column = item.closest('.el-col');
  const target = column || item;
  return Math.round(target.getBoundingClientRect().left);
};

const findColumnGroup = (groups, left) => {
  return groups.find(group => Math.abs(group.left - left) <= COLUMN_TOLERANCE);
};

const getTextMeasureEl = () => {
  if (textMeasureEl) return textMeasureEl;
  textMeasureEl = document.createElement('span');
  textMeasureEl.style.position = 'fixed';
  textMeasureEl.style.left = '-9999px';
  textMeasureEl.style.top = '-9999px';
  textMeasureEl.style.visibility = 'hidden';
  textMeasureEl.style.whiteSpace = 'nowrap';
  textMeasureEl.style.pointerEvents = 'none';
  document.body.appendChild(textMeasureEl);
  return textMeasureEl;
};

const measureLabelWidth = (label, item) => {
  const text = String(label.textContent || '').trim();
  if (!text) return 0;

  const style = window.getComputedStyle(label);
  const measurer = getTextMeasureEl();
  measurer.style.font = style.font;
  measurer.style.letterSpacing = style.letterSpacing;
  measurer.textContent = text;

  const paddingLeft = Number.parseFloat(style.paddingLeft) || 0;
  const paddingRight = Number.parseFloat(style.paddingRight) || 0;
  const requiredWidth = item.classList.contains('is-required') ? REQUIRED_MARK_WIDTH : 0;
  return Math.ceil(measurer.getBoundingClientRect().width + paddingLeft + paddingRight + requiredWidth);
};

const collectLabelGroups = form => {
  const groups = [];
  const items = Array.from(form.querySelectorAll(ITEM_SELECTOR));

  items.forEach(item => {
    if (!isVisible(item) || item.closest('.avue-form__menu')) return;

    const label = getDirectLabel(item);
    if (!label || !isVisible(label)) return;

    const width = measureLabelWidth(label, item);
    if (!width) return;

    const left = getColumnLeft(item);
    let group = findColumnGroup(groups, left);
    if (!group) {
      group = {
        left,
        labels: [],
        width: 0,
      };
      groups.push(group);
    }

    group.labels.push(label);
    group.width = Math.max(group.width, width);
  });

  return groups;
};

const alignFormLabelsByColumn = form => {
  const groups = collectLabelGroups(form);

  groups.forEach(group => {
    group.labels.forEach(label => {
      const width = `${group.width}px`;
      if (label.style.width !== width) {
        label.style.width = width;
      }
      if (label.style.flexBasis !== width) {
        label.style.flexBasis = width;
      }
      if (label.style.justifyContent !== 'flex-end') {
        label.style.justifyContent = 'flex-end';
      }
      if (label.style.textAlign !== 'right') {
        label.style.textAlign = 'right';
      }
    });
  });
};

const alignAllDialogFormLabels = () => {
  document.querySelectorAll(FORM_SELECTOR).forEach(alignFormLabelsByColumn);
};

export const setupDialogFormLabelAlign = () => {
  if (typeof window === 'undefined' || typeof document === 'undefined') return;

  let frameId = 0;
  const scheduleAlign = () => {
    if (frameId) return;
    frameId = window.requestAnimationFrame(() => {
      frameId = 0;
      alignAllDialogFormLabels();
    });
  };

  scheduleAlign();
  window.addEventListener('resize', scheduleAlign);

  const observer = new MutationObserver(scheduleAlign);
  observer.observe(document.body, {
    attributes: true,
    attributeFilter: ['class', 'style'],
    childList: true,
    subtree: true,
  });
};
