import React, {
  useEffect,
  useMemo,
  useState,
  useCallback,
  useRef,
} from 'react';
import Slider from '@mui/material/Slider';
import ToggleButton from '@mui/material/ToggleButton';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import { useWavesurfer } from '@wavesurfer/react';
import RegionsPlugin from 'wavesurfer.js/dist/plugins/regions.esm.js';
import ZoomPlugin from 'wavesurfer.js/dist/plugins/zoom.esm.js';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { ClipMetadata, PlaybackType } from '../../../redux/types';
import { useAppSelector } from '../../hooks';
import PlayStopIcon from '../icons/playStopIcon';
import PlayOverlapIcon from '../icons/playOverlapIcon';
import NameEditDialog from './dialogs/NameEditDialog';
import DeleteClipDialog from './dialogs/DeleteClipDialog';
import TitleBlock from './TitleBlock';
import ClipButtonRow from './ClipButtonRow';

export interface AudioTrimmerProps {
  metadata: ClipMetadata;
  onSave?: (metadata: ClipMetadata) => void;
  onDelete?: (metadata: ClipMetadata) => void;
  onMove?: (newCollection: string, metadata: ClipMetadata) => void;
}

export default function AudioTrimmer({
  metadata,
  onSave,
  onDelete,
  onMove,
}: AudioTrimmerProps) {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id: metadata.filename });
  const rootRef = useRef<HTMLDivElement | null>(null);
  const [isVisible, setIsVisible] = useState(false);
  const [editDialogOpen, setEditDialogOpen] = useState(false);
  const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
  const [volumeInput, setVolumeInput] = useState<number>(metadata.volume ?? 1);
  const collectionNames = useAppSelector((state) =>
    state.collections.map((col) => col.name),
  );

  const handleDialogSave = (newName: string) => {
    if (newName.trim() && newName !== metadata.name) {
      const updated = { ...metadata, name: newName.trim() };
      if (onSave) onSave(updated);
    }
    setEditDialogOpen(false);
  };

  const containerRef = useRef(null);
  // const [clipStart, setClipStart] = useState<number | undefined>(undefined);
  // const [clipEnd, setClipEnd] = useState<number | undefined>(undefined);

  const plugins = useMemo(
    () => [
      RegionsPlugin.create(),
      ZoomPlugin.create({
        scale: 0.25,
      }),
    ],
    [],
  );

  const { wavesurfer, isReady, isPlaying } = useWavesurfer({
    container: containerRef,
    height: 100,
    waveColor: '#ccb1ff',
    progressColor: '#6e44ba',
    hideScrollbar: true,
    plugins,
  });

  // Add this ref to always have the latest metadata
  const metadataRef = useRef(metadata);
  useEffect(() => {
    metadataRef.current = metadata;
  }, [metadata]);

  const onRegionCreated = useCallback(
    (newRegion: any) => {
      if (wavesurfer === null) return;

      const allRegions = (plugins[0] as RegionsPlugin).getRegions();
      let isNew = metadataRef.current.startTime === undefined;

      allRegions.forEach((region) => {
        if (region.id !== newRegion.id) {
          if (
            region.start === newRegion.start &&
            region.end === newRegion.end
          ) {
            newRegion.remove();
            return;
          }
          region.remove();
          isNew = !(region.start === 0 && region.end === 0);
          // console.log('Region replace:', newRegion, region);
        }
      });

      if (isNew) {
        console.log('Region created:', metadataRef.current);
        const updated = {
          ...metadataRef.current,
          startTime: newRegion.start,
          endTime: newRegion.end,
        };
        if (onSave) {
          onSave(updated);
        }
      }
    },
    [plugins, wavesurfer, onSave],
  );

  const onRegionUpdated = useCallback(
    (newRegion: any) => {
      if (wavesurfer === null) return;

      const updated = {
        ...metadataRef.current,
        startTime: newRegion.start,
        endTime: newRegion.end,
      };
      if (onSave) {
        onSave(updated);
      }
    },
    [onSave, wavesurfer],
  );

  useEffect(() => {
    const plugin = plugins[0] as RegionsPlugin;

    if (!isReady) return;
    // console.log('ready, setting up regions plugin', plugin, isReady);
    if (
      metadataRef.current.startTime !== undefined &&
      metadataRef.current.endTime !== undefined
    ) {
      // setClipStart(metadata.startTime);
      // setClipEnd(metadata.endTime);
      // console.log('Adding region from metadata:', metadata);=

      const allRegions = plugin.getRegions();
      // console.log('Existing regions:', allRegions);
      if (
        allRegions.length === 0 ||
        (allRegions.length === 1 &&
          allRegions[0].start === 0 &&
          allRegions[0].end === 0)
      ) {
        // console.log('adding region from metadata:', metadataRef.current);
        plugin.addRegion({
          start: metadataRef.current.startTime,
          end: metadataRef.current.endTime,
          color: 'rgba(132, 81, 224, 0.3)',
          drag: false,
          resize: true,
        });
      }
    } else {
      // setClipStart(0);
      // setClipEnd(wavesurfer ? wavesurfer.getDuration() : 0);
    }
  }, [isReady, plugins]);

  useEffect(() => {
    const plugin = plugins[0] as RegionsPlugin;
    plugin.unAll();
    plugin.on('region-created', onRegionCreated);
    plugin.on('region-updated', onRegionUpdated);
    plugin.enableDragSelection({
      color: 'rgba(132, 81, 224, 0.3)',
    });
  }, [onRegionCreated, onRegionUpdated, plugins]);

  useEffect(() => {
    const node = rootRef.current;
    if (!node) return;
    const observer = new window.IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsVisible(true);
        }
      },
      { threshold: 0.1 },
    );
    observer.observe(node);
    // eslint-disable-next-line consistent-return
    return () => {
      observer.disconnect();
    };
  }, []);

  useEffect(() => {
    if (!isVisible) return;
    let cancelled = false;
    async function fetchAudio() {
      const buffer = await window.audio.loadAudioBuffer(metadata.filename);
      if (cancelled) return;
      if (buffer.buffer && !buffer.error) {
        const audioData = buffer.buffer
          ? new Uint8Array(buffer.buffer)
          : buffer;
        wavesurfer?.loadBlob(new Blob([audioData]));
      }
    }
    fetchAudio();
    // eslint-disable-next-line consistent-return
    return () => {
      cancelled = true;
    };
  }, [isVisible, metadata.filename, wavesurfer]);

  const onPlayPause = () => {
    if (wavesurfer === null) return;
    if (isPlaying) {
      wavesurfer.pause();
    } else {
      const allRegions = (plugins[0] as RegionsPlugin).getRegions();
      if (allRegions.length > 0) {
        wavesurfer.setVolume(metadata.volume ?? 1);
        wavesurfer.play(allRegions[0].start, allRegions[0].end);
      } else {
        wavesurfer.play();
      }
    }
  };

  const formatTime = (seconds: number) => {
    const minutes = Math.floor(seconds / 60);
    const secs = (seconds % 60).toFixed(0);
    return `${minutes}:${secs.padStart(2, '0')}`;
  };

  return (
    <div
      ref={(el) => {
        setNodeRef(el);
        rootRef.current = el;
      }}
      style={{
        transform: CSS.Transform.toString(transform),
        transition,
        position: 'relative',
        alignItems: 'stretch',
      }}
      className="shadow-[0_2px_8px_rgba(0,0,0,0.5)] m-2 rounded-lg bg-darkDrop"
    >
      <NameEditDialog
        open={editDialogOpen}
        onCancel={() => setEditDialogOpen(false)}
        startValue={metadata.name}
        onSave={handleDialogSave}
      />

      <DeleteClipDialog
        open={deleteDialogOpen}
        onCancel={() => setDeleteDialogOpen(false)}
        onDelete={() => {
          setDeleteDialogOpen(false);
          if (onDelete) onDelete(metadata);
        }}
      />
      <div
        // eslint-disable-next-line react/jsx-props-no-spreading
        {...attributes}
        // eslint-disable-next-line react/jsx-props-no-spreading
        {...listeners}
        style={{
          position: 'absolute',
          left: 0,
          top: 0,
          bottom: 0,
          width: '10px',
          borderRadius: '5px 0 0 5px',
          cursor: 'grab',
        }}
        className="bg-neutral-800"
      />
      {/* <div className="flex flex-col"> */}
      <div className="ml-4 mr-2 p-2">
        <div className="grid justify-items-stretch grid-cols-2">
          <TitleBlock
            name={metadata.name}
            filename={metadata.filename}
            onNameClick={() => setEditDialogOpen(true)}
          />
          <ClipButtonRow
            isPlaying={isPlaying}
            collectionNames={collectionNames}
            onPlayPause={onPlayPause}
            onMove={(collectionName) => {
              if (onMove !== undefined) {
                onMove(collectionName, metadata);
              }
            }}
            onDelete={() => setDeleteDialogOpen(true)}
          />
        </div>
        <div className="m-1 wavesurfer-scroll-container">
          <div ref={containerRef} className="wavesurfer-inner" />
        </div>
        <div className="flex justify-between mt-2">
          <span className="w-1/5 flex-none text-sm text-neutral-500 self-center">
            Clip: {formatTime(metadata.startTime ?? 0)} -{' '}
            {formatTime(metadata.endTime ?? 0)}
          </span>
          <div className="w-3/5 flex-1 flex justify-center items-center">
            <Slider
              value={volumeInput}
              min={0}
              max={1}
              step={0.01}
              onChange={(e, newValue) => setVolumeInput(newValue as number)}
              onChangeCommitted={(e, newValue) => {
                const newVolume = newValue as number;
                console.log('Volume change:', newVolume);
                if (onSave) onSave({ ...metadata, volume: newVolume });
              }}
              color="secondary"
              className="p-0 m-0"
            />
          </div>
          <div className="w-1/5 flex justify-end text-sm text-neutral-500">
            <ToggleButtonGroup value={metadata.playbackType}>
              <ToggleButton
                value="playStop"
                color="primary"
                onClick={() => {
                  if (onSave)
                    onSave({
                      ...metadata,
                      playbackType: PlaybackType.PlayStop,
                    });
                }}
              >
                <PlayStopIcon />
              </ToggleButton>
              <ToggleButton
                value="playOverlap"
                color="primary"
                onClick={() => {
                  if (onSave)
                    onSave({
                      ...metadata,
                      playbackType: PlaybackType.PlayOverlap,
                    });
                }}
              >
                <PlayOverlapIcon />
              </ToggleButton>
            </ToggleButtonGroup>
          </div>
        </div>
      </div>
    </div>
  );
}
