// Silence detection segments + non-destructive "remove silence" action.
// Applying silence removal splits each clip at silence boundaries and
// compresses the remaining segments together on the timeline.

import type { Clip, SilenceSegment } from '@/types';
import type { EditorActions, Getter, Setter } from './types';
import { uid } from './types';

export function createSilenceActions(
  set: Setter,
  get: Getter,
): Pick<
  EditorActions,
  'setSilenceSegments' | 'removeSilenceSegment' | 'clearSilence' | 'applySilenceRemoval'
> {
  return {
    setSilenceSegments: (segs) => set({ silenceSegments: segs }),

    removeSilenceSegment: (id) => {
      get().pushHistory('ลบช่วงเงียบ');
      set((s) => ({
        silenceSegments: s.silenceSegments.filter((seg) => seg.id !== id),
      }));
    },

    clearSilence: () => {
      get().pushHistory('ล้างช่วงเงียบ');
      set({ silenceSegments: [] });
    },

    applySilenceRemoval: () => {
      const { silenceSegments, clips } = get();
      if (silenceSegments.length === 0) {
        get().setToast({ message: 'ยังไม่มีช่วงเงียบที่ตรวจพบ', level: 'info' });
        return;
      }
      get().pushHistory('ลบช่วงเงียบทั้งหมด');

      // Group + sort segments per track for sweeping.
      const silByTrack = new Map<string, SilenceSegment[]>();
      for (const seg of silenceSegments) {
        const arr = silByTrack.get(seg.trackId) ?? [];
        arr.push(seg);
        silByTrack.set(seg.trackId, arr);
      }
      for (const arr of silByTrack.values()) {
        arr.sort((a, b) => a.start - b.start);
      }

      const result: Clip[] = [];
      for (const c of clips) {
        const segs = silByTrack.get(c.trackId) ?? [];
        if (segs.length === 0) {
          result.push(c);
          continue;
        }
        // Walk the clip and split around silence ranges.
        let cursor = c.start;
        const segments: { start: number; end: number; sourceIn: number }[] = [];
        for (const seg of segs) {
          const segStart = Math.max(seg.start, c.start);
          const segEnd = Math.min(seg.end, c.start + c.duration);
          if (segStart >= segEnd) continue;
          if (cursor < segStart) {
            segments.push({
              start: cursor,
              end: segStart,
              sourceIn: c.sourceIn + (cursor - c.start),
            });
          }
          cursor = Math.max(cursor, segEnd);
        }
        if (cursor < c.start + c.duration) {
          segments.push({
            start: cursor,
            end: c.start + c.duration,
            sourceIn: c.sourceIn + (cursor - c.start),
          });
        }
        // Re-emit segments, compressing them back-to-back to remove gaps.
        let timelineCursor = c.start;
        for (const seg of segments) {
          const dur = seg.end - seg.start;
          if (dur <= 0.01) continue;
          result.push({
            id: uid(),
            assetId: c.assetId,
            trackId: c.trackId,
            start: timelineCursor,
            duration: dur,
            sourceIn: seg.sourceIn,
          });
          timelineCursor += dur;
        }
      }
      set({ clips: result, silenceSegments: [], currentTime: 0 });
      get().setToast({ message: 'ลบช่วงเงียบเรียบร้อย', level: 'success' });
    },
  };
}