import { HTMLAttributes, useEffect, useRef } from 'react';

import { WebUserEvent } from '@/logging/TrackingEventTypes';
import logWebUserEvent from '@/logging/logWebUserEvent';

export type ImpressionLoggerConfig = {
  event: WebUserEvent;
  threshold?: number;
  disabled?: boolean;
};

type SingleImpressionLoggerProps = ImpressionLoggerConfig & {
  configs?: never; // Ensure configs isn't used with single impression props
};

type MultiImpressionLoggerProps = {
  // Ensure single impresssion props aren't used with configs
  event?: never;
  threshold?: never;
  disabled?: never;
  configs: Array<ImpressionLoggerConfig>;
};

type ImpressionLoggerProps = (
  | SingleImpressionLoggerProps
  | MultiImpressionLoggerProps
) &
  HTMLAttributes<HTMLDivElement>;

export default function ImpressionLogger({
  event,
  threshold = 1.0,
  disabled,
  configs,
  ...otherProps
}: ImpressionLoggerProps) {
  const wrapperRef = useRef<HTMLDivElement>(null);
  const loggedEventIds = useRef(new Set<string>());

  useEffect(() => {
    // Normalize configs
    const normalizedConfigs = configs
      ? configs.map((c) => ({ ...c, threshold: c.threshold ?? 1.0 }))
      : event
        ? [{ event, threshold, disabled }]
        : [];

    // Filter out disabled configs
    const enabledConfigs = normalizedConfigs.filter((c) => !c.disabled);
    if (enabledConfigs.length === 0) return;

    // Collect all thresholds for the observer
    const thresholds = enabledConfigs.map((c) => c.threshold);

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            // Check each config against the current intersection ratio
            enabledConfigs.forEach((config) => {
              const configThreshold = config.threshold;
              const eventId = `${config.event.actionName}-${configThreshold}`;

              if (
                entry.intersectionRatio >= configThreshold &&
                !loggedEventIds.current.has(eventId)
              ) {
                loggedEventIds.current.add(eventId);
                logWebUserEvent(config.event);
              }
            });
          }
        });
      },
      {
        root: document,
        threshold: thresholds,
      }
    );

    if (wrapperRef.current) {
      observer.observe(wrapperRef.current);
    }

    return () => {
      if (wrapperRef.current) {
        observer.unobserve(wrapperRef.current);
      }
    };
  }, [configs, event, threshold, disabled]);

  return <div ref={wrapperRef} {...otherProps} />;
}
