'use client';

import { useEffect } from 'react';

/**
 * Finds the nearest scrollable parent container for an element (e.g., inside a modal or drawer).
 */
export function getScrollParent(element: HTMLElement | null): HTMLElement | null {
  if (!element || typeof window === 'undefined') return null;
  let parent = element.parentElement;
  while (parent && parent !== document.body && parent !== document.documentElement) {
    const style = window.getComputedStyle(parent);
    const overflowY = style.overflowY || '';
    if ((overflowY === 'auto' || overflowY === 'scroll') && parent.scrollHeight > parent.clientHeight) {
      return parent;
    }
    parent = parent.parentElement;
  }
  return null;
}

/**
 * Checks if an element is currently visible in the DOM.
 */
export function isElementVisible(el: HTMLElement | null): boolean {
  if (!el || typeof window === 'undefined') return false;
  if (el.offsetParent === null && el.offsetWidth === 0 && el.offsetHeight === 0) {
    return false;
  }
  const style = window.getComputedStyle(el);
  return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';
}

/**
 * Smoothly scrolls toward the first error on the page or inside a given container.
 * Prioritizes:
 * 1. Error alerts & banners (`[data-error-banner]`, `[role="alert"]`, `#form-error-banner`, `.form-error-banner`)
 * 2. Inputs/fields with `aria-invalid="true"` or error border classes
 * 3. Any field error label or message container (`.text-rose-500`, `.bg-rose-50`)
 */
export function scrollToFirstError(container?: HTMLElement | null): boolean {
  if (typeof window === 'undefined' || typeof document === 'undefined') return false;

  // Defer slightly so React has committed state and DOM updates to the document
  const timer = setTimeout(() => {
    const root: Document | HTMLElement = container || document;

    // 1. Check for error banner at the top of the form
    const banner = root.querySelector<HTMLElement>(
      '#form-error-banner, [data-error-banner], [role="alert"].bg-rose-50, .form-error-banner'
    );
    if (banner && isElementVisible(banner)) {
      performSmoothScroll(banner);
      return;
    }

    // 2. Check for invalid inputs or fields with error styling
    const invalidInput = root.querySelector<HTMLElement>(
      'input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"], ' +
      'input:invalid, select:invalid, textarea:invalid, ' +
      '.border-rose-400, .border-rose-500, .border-rose-300, .border-red-500, ' +
      'input.bg-rose-50\\/20, select.bg-rose-50\\/20'
    );
    if (invalidInput && isElementVisible(invalidInput)) {
      performSmoothScroll(invalidInput);
      try {
        if (typeof (invalidInput as any).focus === 'function') {
          (invalidInput as any).focus({ preventScroll: true });
        }
      } catch {}
      return;
    }

    // 3. Check for any error text or badge
    const errorText = root.querySelector<HTMLElement>(
      'p.text-rose-500, span.text-rose-500, p.text-red-500, span.text-red-500, ' +
      '.bg-rose-50, .bg-red-50, .text-rose-600'
    );
    if (errorText && isElementVisible(errorText)) {
      performSmoothScroll(errorText);
      return;
    }

    // 4. Fallback: general role="alert"
    const generalAlert = root.querySelector<HTMLElement>('[role="alert"]');
    if (generalAlert && isElementVisible(generalAlert)) {
      performSmoothScroll(generalAlert);
      return;
    }
  }, 40);

  return true;
}

/**
 * Performs smooth scroll to the target element with sticky header offset consideration.
 */
export function performSmoothScroll(element: HTMLElement) {
  if (!element || typeof window === 'undefined') return;

  const scrollParent = getScrollParent(element);
  if (scrollParent) {
    // If inside a scrollable modal / container, scroll that container
    element.scrollIntoView({ behavior: 'smooth', block: 'center' });
  } else {
    // Top-level document scrolling with header offset (90px)
    const rect = element.getBoundingClientRect();
    const currentScrollY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
    const targetY = Math.max(0, currentScrollY + rect.top - 100);

    window.scrollTo({
      top: targetY,
      behavior: 'smooth',
    });
  }
}

/**
 * React hook that automatically scrolls to the first error whenever error state becomes active.
 */
export function useFormErrorScroll(
  triggerErrors: any,
  containerRef?: React.RefObject<HTMLElement | null>
) {
  useEffect(() => {
    if (!triggerErrors) return;

    let hasError = false;
    if (typeof triggerErrors === 'string') {
      hasError = triggerErrors.trim().length > 0;
    } else if (Array.isArray(triggerErrors)) {
      hasError = triggerErrors.length > 0;
    } else if (typeof triggerErrors === 'object' && triggerErrors !== null) {
      hasError = Object.keys(triggerErrors).length > 0;
    } else {
      hasError = Boolean(triggerErrors);
    }

    if (hasError) {
      scrollToFirstError(containerRef?.current || null);
    }
  }, [triggerErrors, containerRef]);
}

// Auto-attach global HTML5 invalid event listener to smoothly scroll toward native form validation errors
if (typeof window !== 'undefined') {
  window.addEventListener(
    'invalid',
    (e: Event) => {
      const target = e.target as HTMLElement;
      if (target && isElementVisible(target)) {
        performSmoothScroll(target);
      }
    },
    true
  );
}
