import React, { useState, useRef, useEffect, useLayoutEffect, useCallback, memo } from 'react';
import PropTypes from 'prop-types';
import './VolumeSlider.css'; // Keep the same CSS for now
import { useMixersContext } from '../../context/MixersContext';
import useFaderHelpers from '../../hooks/useFaderHelpers';

const SessionTrackGain = memo(function SessionTrackGain({ mixers, gainType, controlGroup, sessionController, orientation = 'vertical' }) {

  const mixerHelper = useMixersContext();
  const faderHelpers = useFaderHelpers();
  const [isDragging, setIsDragging] = useState(false);
  const sliderTrackRef = useRef(null);
  const sliderThumbRef = useRef(null);
  const sliderFillRef = useRef(null);

  // Get the mixer to work with
  const getMixer = useCallback(() => {
    // Now mixers is a real mixer object directly, not a nested structure
    return mixers;
  }, [mixers]);

  // Initialize value from mixer
  const getInitialValue = useCallback(() => {
    const mixer = getMixer();
    if (mixer) {
      return faderHelpers.convertAudioTaperToPercent(mixer.volume_left);
    }
    return 50; // fallback
  }, [getMixer, faderHelpers]);

  const [currentValue, setCurrentValue] = useState(getInitialValue);
  const [displayedVolume, setDisplayedVolume] = useState(getMixer()?.volume_left || 0);
  const prevVolumeRef = useRef();

  // Update value when mixer changes or volume changes
  useEffect(() => {
    const mixer = mixers;
    const currentVolume = mixer?.volume_left;

    // Only update if we have valid volume data
    // Don't reset to fallback if mixer temporarily becomes undefined during re-renders
    if (mixer && currentVolume !== undefined && currentVolume !== prevVolumeRef.current) {
      prevVolumeRef.current = currentVolume;
      const newValue = faderHelpers.convertAudioTaperToPercent(currentVolume);
      setCurrentValue(newValue);
      setDisplayedVolume(currentVolume);
      mixerHelper.initGain(mixer);
    }
  }, [mixers, faderHelpers, mixerHelper]);

  // Function to calculate and update the slider's position and value
  const updateSlider = useCallback(
    async clientPos => {
      if (!sliderTrackRef.current) return;

      const trackRect = sliderTrackRef.current.getBoundingClientRect();
      let positionInTrack, trackSize;

      if (orientation === 'vertical') {
        // Calculate position from the BOTTOM of the track
        positionInTrack = trackRect.bottom - clientPos;
        trackSize = trackRect.height;
      } else {
        // Calculate position from the LEFT of the track
        positionInTrack = clientPos - trackRect.left;
        trackSize = trackRect.width;
      }

      // Clamp the position within the valid track bounds (0 to trackSize)
      const clampedPosition = Math.max(0, Math.min(positionInTrack, trackSize));

      // Calculate the percentage
      const percentage = (clampedPosition / trackSize) * 100;

      // Update the mixer - now mixers is a real mixer object directly
      if (mixers) {
        await mixerHelper.faderChanged(
          { percentage, dragging: isDragging },
          mixers, // Pass the real mixer object directly
          gainType,
          controlGroup
        );
      }


      // Update local state for UI
      setCurrentValue(Math.round(percentage));

      // Update displayed volume during dragging
      const newVolumeDb = faderHelpers.convertPercentToAudioTaper(percentage);
      setDisplayedVolume(newVolumeDb);

      // Directly manipulating the DOM for immediate visual updates during drag
      if (orientation === 'vertical') {
        sliderThumbRef.current.style.bottom = `${clampedPosition}px`;
        sliderFillRef.current.style.height = `${clampedPosition}px`;
      } else {
        sliderThumbRef.current.style.left = `${clampedPosition}px`;
        sliderFillRef.current.style.width = `${clampedPosition}px`;
      }
    },
    [orientation, mixers, faderHelpers, mixerHelper, isDragging, gainType, controlGroup]
  );

  // Mouse Move and Up Handlers (Global listeners)
  const handleMouseMove = useCallback(
    e => {
      e.preventDefault(); // Prevent text selection
      updateSlider(orientation === 'vertical' ? e.clientY : e.clientX);
    },
    [updateSlider, orientation]
  );

  const handleMouseUp = useCallback(() => {
    setIsDragging(false);
    window.removeEventListener('mousemove', handleMouseMove);
    window.removeEventListener('mouseup', handleMouseUp);
    if (sliderThumbRef.current) {
      sliderThumbRef.current.classList.remove('dragging');
    }
  }, [handleMouseMove]);

  // Mouse Down Handler (Starts the drag)
  const handleMouseDown = e => {
    e.preventDefault();
    setIsDragging(true);
    // Add global listeners when dragging starts
    window.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('mouseup', handleMouseUp);
    if (sliderThumbRef.current) {
      sliderThumbRef.current.classList.add('dragging');
    }
  };

  // Click on Track Handler (Jump to value)
  const handleTrackClick = e => {
    updateSlider(orientation === 'vertical' ? e.clientY : e.clientX);
  };

  // Update the slider position when value changes
  // Using useLayoutEffect to ensure visual update happens synchronously before paint
  useLayoutEffect(() => {
    if (!sliderTrackRef.current || !sliderThumbRef.current || !sliderFillRef.current) {
      return;
    }
    const percentage = currentValue / 100;
    if (orientation === 'vertical') {
      const trackHeight = sliderTrackRef.current.clientHeight;
      const clampedPosition = trackHeight * percentage;
      sliderThumbRef.current.style.bottom = `${clampedPosition}px`;
      sliderFillRef.current.style.height = `${clampedPosition}px`;
    } else {
      const trackWidth = sliderTrackRef.current.clientWidth;
      const clampedPosition = trackWidth * percentage;
      sliderThumbRef.current.style.left = `${clampedPosition}px`;
      sliderFillRef.current.style.width = `${clampedPosition}px`;
    }
  }, [currentValue, orientation]);

  return (
    <div>
      <div id="slider-value">
        <small>{displayedVolume}db</small>
      </div>
      <div
        className={orientation === 'vertical' ? 'vertical-slider-container' : 'horizontal-slider-container'}
        onClick={handleTrackClick}
      >
        <div className="slider-track" ref={sliderTrackRef}>
          <div className={`slider-fill ${orientation === 'horizontal' ? 'horizontal' : ''}`} ref={sliderFillRef} />
          <div
            className={`slider-thumb ${orientation === 'horizontal' ? 'horizontal' : ''}`}
            ref={sliderThumbRef}
            onMouseDown={handleMouseDown}
          />
        </div>
      </div>
    </div>
  );
});

SessionTrackGain.displayName = 'SessionTrackGain';

SessionTrackGain.propTypes = {
  mixers: PropTypes.object,
  gainType: PropTypes.string,
  controlGroup: PropTypes.string,
  sessionController: PropTypes.object,
  orientation: PropTypes.string
};

export default SessionTrackGain;
