'use client';

// Main timeline editor — composes the toolbar, ruler, track rows, clips,
// silence overlays, subtitle markers, and the playhead. All heavy lifting
// (drag, snap, detection, etc.) lives in `timeline/*.tsx`.

import { useCallback, useMemo, useRef, useState } from 'react';
import { useEditor, selectTimelineDuration } from '@/store/editor';
import { formatTimeShort } from '@/lib/media';
import { TRACK_HEIGHT, TRACK_LABEL_WIDTH, RULER_HEIGHT } from './timeline/constants';
import { snapTime } from './timeline/snap';
import { detectAllSilences } from './timeline/detectSilence';
import { TimelineToolbar } from './timeline/TimelineToolbar';
import { TrackLabel } from './timeline/TrackLabel';
import { ClipBlock } from './timeline/ClipBlock';
import { SilenceBlock } from './timeline/SilenceBlock';
import { Ruler } from './timeline/Ruler';
import { SubtitleMarkers } from './timeline/SubtitleMarkers';
import { GhostWaveform } from './timeline/GhostWaveform';

export function Timeline() {
  const tracks = useEditor((s) => s.tracks);
  const clips = useEditor((s) => s.clips);
  const assets = useEditor((s) => s.assets);
  const selection = useEditor((s) => s.selection);
  const setSelection = useEditor((s) => s.setSelection);
  const currentTime = useEditor((s) => s.currentTime);
  const setCurrentTime = useEditor((s) => s.setCurrentTime);
  const zoom = useEditor((s) => s.zoom);
  const silenceSegments = useEditor((s) => s.silenceSegments);
  const setSilenceSegments = useEditor((s) => s.setSilenceSegments);
  const removeSilenceSegment = useEditor((s) => s.removeSilenceSegment);
  const applySilenceRemoval = useEditor((s) => s.applySilenceRemoval);
  const addClip = useEditor((s) => s.addClip);
  const updateClip = useEditor((s) => s.updateClip);
  const pushHistory = useEditor((s) => s.pushHistory);
  const removeTrack = useEditor((s) => s.removeTrack);
  const updateTrack = useEditor((s) => s.updateTrack);
  const setToast = useEditor((s) => s.setToast);
  const exportSettings = useEditor((s) => s.exportSettings);

  const duration = useEditor(selectTimelineDuration);

  const scrollRef = useRef<HTMLDivElement | null>(null);
  const [snapping, setSnapping] = useState(true);
  const [detecting, setDetecting] = useState(false);
  const [hoverTime, setHoverTime] = useState<number | null>(null);

  const minWidth = useMemo(
    () => Math.max(30, duration + 5) * zoom,
    [duration, zoom],
  );

  const pxToTime = useCallback((px: number) => px / zoom, [zoom]);
  const timeToPx = useCallback((t: number) => t * zoom, [zoom]);

  function onTrackDrop(e: React.DragEvent, trackId: string) {
    e.preventDefault();
    const track = tracks.find((t) => t.id === trackId);
    if (!track) return;
    const assetId = e.dataTransfer.getData('application/x-capcut-asset');
    if (!assetId) return;
    const asset = assets.find((a) => a.id === assetId);
    if (!asset) return;
    if ((asset.kind === 'video' || asset.kind === 'image') && track.kind !== 'video') {
      setToast({ message: 'ลากวิดีโอ/ภาพลงแทร็กวิดีโอเท่านั้น', level: 'error' });
      return;
    }
    if (asset.kind === 'audio' && track.kind !== 'audio') {
      setToast({ message: 'ลากเสียงลงแทร็กเสียงเท่านั้น', level: 'error' });
      return;
    }
    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
    const x = e.clientX - rect.left + (scrollRef.current?.scrollLeft ?? 0);
    const start = Math.max(0, pxToTime(x));
    addClip({
      assetId: asset.id,
      trackId: track.id,
      start: snapTime(start, zoom, currentTime, clips, snapping),
      duration: asset.duration,
      sourceIn: 0,
    });
    setToast({ message: `เพิ่มคลิปลงแทร็ก ${track.name}`, level: 'success' });
  }

  function onRulerClick(e: React.MouseEvent) {
    const target = e.currentTarget as HTMLElement;
    const rect = target.getBoundingClientRect();
    const x = e.clientX - rect.left + (scrollRef.current?.scrollLeft ?? 0);
    setCurrentTime(Math.max(0, pxToTime(x)));
  }

  async function runDetection() {
    // Short-circuit: if there are no audio clips on the timeline, show a
    // clear error and don't waste time running the detector.
    const audioTracks = tracks.filter((t) => t.kind === 'audio');
    const audioClips = clips.filter((c) => audioTracks.some((t) => t.id === c.trackId));
    if (audioClips.length === 0) {
      setToast({
        message: 'ไม่มีคลิปเสียง — ลากไฟล์เสียง (หรือวิดีโอที่มีเสียง) ลงแทร็กเสียงก่อน',
        level: 'error',
      });
      return;
    }
    setDetecting(true);
    try {
      const segs = await detectAllSilences({
        tracks,
        clips,
        assets,
        settings: exportSettings,
        setToast,
      });
      setSilenceSegments(segs);
      // Auto-suggest the next step (Cut all) by flashing a success toast that
      // tells the user what to do next.
      if (segs.length > 0) {
        setToast({
          message: `พบ ${segs.length} ช่วงเงียบ — กด "ลบทั้งหมด" เพื่อลบออกจากไทม์ไลน์`,
          level: 'success',
        });
      }
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'การตรวจจับล้มเหลว';
      setToast({ message: `ตรวจจับล้มเหลว: ${msg}`, level: 'error' });
    } finally {
      setDetecting(false);
    }
  }

  /** 1-click flow: detect silences, then immediately apply removal. */
  async function runDetectAndCut() {
    const audioTracks = tracks.filter((t) => t.kind === 'audio');
    const audioClips = clips.filter((c) => audioTracks.some((t) => t.id === c.trackId));
    if (audioClips.length === 0) {
      setToast({
        message: 'ไม่มีคลิปเสียง — ลากไฟล์เสียง (หรือวิดีโอที่มีเสียง) ลงแทร็กเสียงก่อน',
        level: 'error',
      });
      return;
    }
    setDetecting(true);
    try {
      const segs = await detectAllSilences({
        tracks,
        clips,
        assets,
        settings: exportSettings,
        setToast,
      });
      if (segs.length === 0) {
        // detectAllSilences already toasts an info message.
        return;
      }
      setSilenceSegments(segs);
      // Apply removal immediately.
      applySilenceRemoval();
      setToast({
        message: `ตัดช่วงเงียบ ${segs.length} ช่วงออกจากไทม์ไลน์แล้ว`,
        level: 'success',
      });
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'การตัดช่วงเงียบล้มเหลว';
      setToast({ message: `ตัดช่วงเงียบล้มเหลว: ${msg}`, level: 'error' });
    } finally {
      setDetecting(false);
    }
  }

  return (
    <div className="h-full flex flex-col bg-capcut-dark">
      <TimelineToolbar
        snapping={snapping}
        onToggleSnap={() => setSnapping(!snapping)}
        detecting={detecting}
        onDetect={runDetection}
        onDetectAndCut={runDetectAndCut}
      />

      <div className="flex-1 min-h-0 flex">
        <div
          className="shrink-0 border-r border-capcut-border bg-capcut-dark"
          style={{ width: TRACK_LABEL_WIDTH }}
        >
          <div style={{ height: RULER_HEIGHT }} className="border-b border-capcut-border" />
          {tracks.map((t) => (
            <TrackLabel
              key={t.id}
              track={t}
              onRemove={() => removeTrack(t.id)}
              onUpdate={updateTrack}
            />
          ))}
        </div>

        <div ref={scrollRef} className="flex-1 overflow-x-auto overflow-y-hidden relative">
          <div style={{ minWidth: minWidth, width: 'max-content' }}>
            <div
              className="sticky top-0 z-20 bg-capcut-dark border-b border-capcut-border"
              style={{ height: RULER_HEIGHT }}
              onClick={onRulerClick}
              onMouseMove={(e) => {
                const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
                setHoverTime(pxToTime(e.clientX - rect.left));
              }}
              onMouseLeave={() => setHoverTime(null)}
            >
              <Ruler duration={Math.max(30, duration + 5)} zoom={zoom} hoverTime={hoverTime} />
            </div>

            <div className="relative">
              {tracks.map((track) => {
                const trackClips = clips.filter((c) => c.trackId === track.id);
                const trackSilence = silenceSegments.filter((s) => s.trackId === track.id);
                return (
                  <div
                    key={track.id}
                    className={`relative border-b border-capcut-border/50 ${
                      track.kind === 'video' ? 'bg-capcut-black/40' : 'bg-capcut-black/60'
                    }`}
                    style={{ height: TRACK_HEIGHT }}
                    onDragOver={(e) => e.preventDefault()}
                    onDrop={(e) => onTrackDrop(e, track.id)}
                  >
                    {trackClips.length === 0 && (
                      <>
                        <GhostWaveform track={track} width={minWidth} />
                        <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
                          <span className="text-[10px] text-capcut-muted/60 italic">
                            ลากไฟล์{track.kind === 'video' ? 'วิดีโอ' : 'เสียง'}จากไลบรารีมาวางที่นี่
                          </span>
                        </div>
                      </>
                    )}
                    {trackClips.map((clip) => (
                      <ClipBlock
                        key={clip.id}
                        clip={clip}
                        track={track}
                        zoom={zoom}
                        selected={selection.clipId === clip.id}
                        assets={assets}
                        onSelect={() => setSelection({ clipId: clip.id, trackId: track.id })}
                        onChange={(patch) => updateClip(clip.id, patch)}
                        onCommit={() => pushHistory('ย้าย/ปรับคลิป')}
                      />
                    ))}
                    {track.kind === 'audio' &&
                      trackSilence.map((seg) => (
                        <SilenceBlock
                          key={seg.id}
                          seg={seg}
                          zoom={zoom}
                          onRemove={() => removeSilenceSegment(seg.id)}
                        />
                      ))}
                  </div>
                );
              })}
            </div>

            {/* Playhead — diamond cap + vertical line */}
            <div
              className="absolute top-0 bottom-0 pointer-events-none z-30"
              style={{
                left: timeToPx(currentTime) - 0.5,
                width: 1,
                background: 'linear-gradient(to bottom, #ff8a3d 0%, #ff8a3d 65%, rgba(255,138,61,0.4) 100%)',
                boxShadow: '0 0 8px rgba(255,138,61,0.6)',
              }}
            >
              <svg
                width="12"
                height="10"
                viewBox="0 0 12 10"
                style={{ position: 'absolute', top: -2, left: -5.5, filter: 'drop-shadow(0 0 4px rgba(255,138,61,0.6))' }}
              >
                <path d="M6 10 L0 0 L12 0 Z" fill="#ff8a3d" />
              </svg>
            </div>
            <div
              className="absolute top-3 bottom-0 pointer-events-none z-30"
              style={{
                left: timeToPx(currentTime),
                width: 0,
              }}
            >
              <div
                className="absolute -top-1 -left-1.5 w-3 h-3 bg-capcut-orange rotate-45 shadow"
                style={{ boxShadow: '0 0 8px rgba(255,138,61,0.6)' }}
              />
            </div>

            <SubtitleMarkers zoom={zoom} />
          </div>
        </div>
      </div>

      <div className="h-6 px-3 border-t border-capcut-border bg-capcut-dark text-[10px] text-capcut-muted flex items-center justify-between shrink-0">
        <span>
          {tracks.length} แทร็ก · {clips.length} คลิป · ความยาวรวม {formatTimeShort(duration)}
        </span>
        <span>Space: เล่น/หยุด · J/L: ±1s · I/O: ตั้ง in/out · S: แยกคลิป · Ctrl+Z: ย้อนกลับ</span>
      </div>
    </div>
  );
}