// Clip + track + asset action creators — the "media library + timeline" domain.

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

export function createMediaActions(
  set: Setter,
  get: Getter,
): Pick<
  EditorActions,
  | 'addAsset'
  | 'removeAsset'
  | 'addTrack'
  | 'removeTrack'
  | 'updateTrack'
  | 'addClip'
  | 'updateClip'
  | 'removeClip'
  | 'splitClipAtCurrent'
  | 'addTextOverlay'
  | 'updateTextOverlay'
  | 'removeTextOverlay'
> {
  return {
    addAsset: (asset) => {
      // No history push — assets are file-backed, undoable independently.
      set((s) => ({ assets: [...s.assets, asset] }));
    },

    removeAsset: (id) => {
      set((s) => ({
        assets: s.assets.filter((a) => a.id !== id),
        clips: s.clips.filter((c) => c.assetId !== id),
      }));
    },

    addTrack: (kind) => {
      get().pushHistory('เพิ่มแทร็ก');
      set((s) => {
        const idx = s.tracks.filter((t) => t.kind === kind).length + 1;
        const namePrefix = kind === 'video' ? 'วิดีโอ' : 'เสียง';
        // Cycle PIP positions so the 2nd/3rd/4th video track don't all stack.
        const videoTracks = s.tracks.filter((t) => t.kind === 'video');
        const pipCycle: ('pip-br' | 'pip-tl' | 'pip-tr' | 'pip-bl' | 'pip-c')[] = [
          'pip-br',
          'pip-tl',
          'pip-tr',
          'pip-bl',
          'pip-c',
        ];
        const isFirstVideo = kind === 'video' && videoTracks.length === 0;
        const track: Track = {
          id: uid(),
          kind,
          name: `${namePrefix} ${idx}`,
          volume: 1,
          muted: false,
          background: kind === 'video' ? { color: '#000000', blur: false } : undefined,
          noiseReduction: kind === 'audio' ? { enabled: false, amount: 0.5 } : undefined,
          videoPosition: kind === 'video'
            ? (isFirstVideo ? 'full' : pipCycle[(videoTracks.length - 1) % pipCycle.length])
            : undefined,
          videoScale: kind === 'video' ? (isFirstVideo ? 1 : 0.3) : undefined,
          videoOpacity: kind === 'video' ? 1 : undefined,
        };
        return { tracks: [...s.tracks, track] };
      });
    },

    removeTrack: (id) => {
      get().pushHistory('ลบแทร็ก');
      set((s) => ({
        tracks: s.tracks.filter((t) => t.id !== id),
        clips: s.clips.filter((c) => c.trackId !== id),
        silenceSegments: s.silenceSegments.filter((seg) => seg.trackId !== id),
      }));
    },

    updateTrack: (id, patch) => {
      set((s) => ({
        tracks: s.tracks.map((t) => (t.id === id ? { ...t, ...patch } : t)),
      }));
    },

    addClip: (clip) => {
      const id = uid();
      get().pushHistory('เพิ่มคลิป');
      set((s) => ({ clips: [...s.clips, { ...clip, id }] }));
      return id;
    },

    updateClip: (id, patch) => {
      set((s) => ({
        clips: s.clips.map((c) => (c.id === id ? { ...c, ...patch } : c)),
      }));
    },

    addTextOverlay: (overlay: Omit<TextOverlay, 'id'>) => {
      const id = uid();
      get().pushHistory('เพิ่มข้อความลอย');
      set((s) => ({ textOverlays: [...s.textOverlays, { ...overlay, id }] }));
      return id;
    },

    updateTextOverlay: (id, patch) => {
      set((s) => ({
        textOverlays: s.textOverlays.map((t) => (t.id === id ? { ...t, ...patch } : t)),
      }));
    },

    removeTextOverlay: (id) => {
      get().pushHistory('ลบข้อความลอย');
      set((s) => ({ textOverlays: s.textOverlays.filter((t) => t.id !== id) }));
    },

    removeClip: (id) => {
      get().pushHistory('ลบคลิป');
      set((s) => ({
        clips: s.clips.filter((c) => c.id !== id),
        selection: s.selection.clipId === id ? {} : s.selection,
      }));
    },

    splitClipAtCurrent: () => {
      const t = get().currentTime;
      const clips = get().clips;
      const targets = clips.filter(
        (c) => t > c.start + 0.05 && t < c.start + c.duration - 0.05,
      );
      if (targets.length === 0) {
        get().setToast({
          message: 'เลื่อน playhead ไปอยู่ในคลิปก่อนแล้วลองอีกครั้ง',
          level: 'info',
        });
        return;
      }
      get().pushHistory('แยกคลิป');
      const next: Clip[] = [];
      for (const c of clips) {
        if (!targets.find((tg) => tg.id === c.id)) {
          next.push(c);
          continue;
        }
        const offset = t - c.start;
        next.push({ ...c, duration: offset });
        next.push({
          ...c,
          id: uid(),
          start: t,
          duration: c.duration - offset,
          sourceIn: c.sourceIn + offset,
        });
      }
      set({ clips: next });
    },
  };
}