// AI Editor: 1-click highlight reel generator.
//
// Runs scene detection via canvas frame hashing + audio loudness analysis
// from the audio buffer. Scores segments and packs the top K into a fresh
// timeline.

'use client';

import { useState } from 'react';
import { Sparkles, Loader2, Wand2 } from 'lucide-react';
import { useEditor } from '@/store/editor';
import { uid } from '@/store/editor/types';
import { Section, NumberField } from './FormFields';
import {
  scoreHighlights,
  detectScenesViaCanvas,
  computeLoudness,
  segmentsToClips,
} from '@/lib/ai/score-segments';
import { detectFillerWords, combineTrimCandidates, applyTrimThreshold, totalCutSeconds } from '@/lib/ai/smart-trim';
import { computeHeatmap, summariseHeatmap } from '@/lib/ai/engagement-heatmap';

type Phase = 'idle' | 'scenes' | 'loudness' | 'scoring' | 'done';

export function AutoEditProperties() {
  const assets = useEditor((s) => s.assets);
  const tracks = useEditor((s) => s.tracks);
  const pushHistory = useEditor((s) => s.pushHistory);
  const setToast = useEditor((s) => s.setToast);

  const [busy, setBusy] = useState(false);
  const [phase, setPhase] = useState<Phase>('idle');
  const [progress, setProgress] = useState(0);
  const [targetSec, setTargetSec] = useState(30);
  const [maxSegment, setMaxSegment] = useState(6);
  const [trimBusy, setTrimBusy] = useState(false);
  const [trimSummary, setTrimSummary] = useState<{ count: number; seconds: number } | null>(null);

  async function run() {
    if (busy) return;
    const videoAsset = assets.find((a) => a.kind === 'video');
    if (!videoAsset) {
      setToast({ message: 'ต้องมีวิดีโอในไลบรารีก่อน', level: 'error' });
      return;
    }
    setBusy(true);
    setProgress(0);
    setPhase('scenes');
    try {
      // Step 1: scene detection via canvas
      setToast({ message: 'กำลังตรวจจับฉากตัดต่อ...', level: 'info' });
      const sceneChanges = await detectScenesViaCanvas(videoAsset, 0.15, 60);
      setProgress(30);

      // Step 2: audio loudness — prefer a separate audio asset, fall back
      // to the video's built-in audio (decode via Web Audio first, extract
      // via FFmpeg.wasm if that fails).
      setPhase('loudness');
      setToast({ message: 'กำลังวิเคราะห์ระดับเสียง...', level: 'info' });
      let audioBuffer: AudioBuffer | undefined;
      const audioAsset = assets.find((a) => a.kind === 'audio');
      if (audioAsset?.audioBuffer) {
        audioBuffer = audioAsset.audioBuffer;
      } else if (videoAsset.audioBuffer) {
        audioBuffer = videoAsset.audioBuffer;
      } else if (videoAsset.kind === 'video') {
        try {
          const { extractAudioFromVideo } = await import('@/lib/ffmpeg');
          const resp = await fetch(videoAsset.url);
          const blob = await resp.blob();
          const file = new File([blob], videoAsset.name, { type: blob.type || 'video/mp4' });
          const extracted = await extractAudioFromVideo(file);
          audioBuffer = extracted.audioBuffer;
        } catch {
          audioBuffer = undefined;
        }
      }
      const { loudnessDb, windowStarts } = computeLoudness(audioBuffer, 0.5);
      setProgress(60);

      // Step 3: scoring + selection
      setPhase('scoring');
      setToast({ message: 'AI กำลังเลือกช่วงไฮไลต์...', level: 'info' });
      const result = scoreHighlights(
        { asset: videoAsset, sceneChanges, loudnessDb, rmsWindowsStart: windowStarts },
        {
          targetDurationSec: targetSec,
          maxSegmentSec: maxSegment,
          minSegmentSec: 1.5,
        },
      );
      setProgress(90);

      if (result.segments.length === 0) {
        setToast({ message: 'ไม่พบช่วงที่น่าสนใจ — ลองเพิ่ม target duration', level: 'info' });
        return;
      }

      // Step 4: build new timeline (keep current tracks; add clips to a fresh pair).
      pushHistory('AI ตัดต่อ');
      const newVideoTrackId = uid();
      const newAudioTrackId = uid();
      const newVideoTrack = {
        id: newVideoTrackId,
        kind: 'video' as const,
        name: 'วิดีโอ AI',
        volume: 1,
        muted: false,
        background: { color: '#000000', blur: false },
      };
      const newAudioTrack = {
        id: newAudioTrackId,
        kind: 'audio' as const,
        name: 'เสียง AI',
        volume: 1,
        muted: false,
        noiseReduction: { enabled: false, amount: 0.5 },
      };
      const newClips = segmentsToClips(
        result.segments,
        videoAsset.id,
        newVideoTrackId,
        newAudioTrackId,
      ).map((c) => ({ ...c, id: uid() }));

      useEditor.setState((s) => ({
        tracks: [...s.tracks, newVideoTrack, newAudioTrack],
        clips: [...s.clips, ...newClips],
      }));

      setPhase('done');
      setProgress(100);
      setToast({
        message: `AI ตัดให้แล้ว ${result.segments.length} ช่วง · ${result.totalDuration.toFixed(1)}s จาก ${videoAsset.duration.toFixed(1)}s`,
        level: 'success',
      });
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'AI ตัดล้มเหลว';
      setToast({ message: `AI ตัดล้มเหลว: ${msg}`, level: 'error' });
    } finally {
      setBusy(false);
      setTimeout(() => {
        setPhase('idle');
        setProgress(0);
      }, 1500);
    }
  }

  return (
    <Section title="AI ตัดต่ออัตโนมัติ" icon={<Wand2 size={14} />}>
      <div className="space-y-2">
        <div className="rounded-md border border-capcut-purple/30 bg-capcut-purple/5 p-2 space-y-2">
          <div className="flex items-center gap-1.5 text-[11px] font-semibold text-capcut-purple">
            <Sparkles size={12} /> ตัดไฮไลต์ให้อัตโนมัติ
          </div>
          <p className="text-[10px] text-capcut-muted leading-snug">
            AI จะวิเคราะห์ฉาก + ระดับเสียง แล้วเลือกช่วงที่น่าสนใจที่สุดมาต่อกัน
          </p>
          <NumberField
            label="เป้าความยาว (วินาที)"
            value={targetSec}
            step={5}
            min={10}
            max={300}
            onChange={(v) => setTargetSec(Math.max(10, Math.min(300, Math.round(v))))}
          />
          <NumberField
            label="ความยาวต่อช่วงสูงสุด (วินาที)"
            value={maxSegment}
            step={1}
            min={2}
            max={20}
            onChange={(v) => setMaxSegment(Math.max(2, Math.min(20, Math.round(v))))}
          />
          <button
            type="button"
            onClick={run}
            disabled={busy || assets.length === 0}
            className="w-full h-9 rounded-md bg-gradient-to-r from-capcut-purple to-capcut-blue hover:opacity-90 text-white text-xs font-medium flex items-center justify-center gap-1.5 disabled:opacity-60"
          >
            {busy ? (
              <>
                <Loader2 size={12} className="animate-spin" /> {phaseLabel(phase)}
              </>
            ) : (
              <>
                <Wand2 size={12} /> 🪄 AI ตัดให้
              </>
            )}
          </button>
          {busy && (
            <div className="space-y-1">
              <div className="h-1 bg-capcut-surface rounded overflow-hidden">
                <div
                  className="h-full bg-gradient-to-r from-capcut-purple to-capcut-blue transition-all"
                  style={{ width: `${progress}%` }}
                />
              </div>
              <div className="text-[10px] text-capcut-muted text-center">{phaseLabel(phase)} · {progress}%</div>
            </div>
          )}
        </div>

        {/* V22.4 — Smart Trim: detect filler words + silence */}
        <div className="rounded-md border border-capcut-orange/30 bg-capcut-orange/5 p-2 space-y-2">
          <div className="flex items-center gap-1.5 text-[11px] font-semibold text-capcut-orange">
            <Sparkles size={12} /> Smart Trim (คำติดปาก + ความเงียบ)
          </div>
          <p className="text-[10px] text-capcut-muted leading-snug">
            หา &ldquo;อ่า/เอ่อ/uh/um&rdquo; + ช่วงเงียบ → ตัดอัตโนมัติ
          </p>
          <button
            type="button"
            onClick={async () => {
              if (trimBusy) return;
              setTrimBusy(true);
              try {
                const s = useEditor.getState();
                const fillerCands = detectFillerWords(s.subtitles);
                // Use existing silence segments as 'silence' candidates
                const silCands = s.silenceSegments.map((sg) => ({
                  start: sg.start,
                  end: sg.end,
                  kind: 'silence' as const,
                  score: 0.8,
                }));
                const merged = combineTrimCandidates(silCands, fillerCands);
                const filtered = applyTrimThreshold(merged);
                setTrimSummary({
                  count: filtered.length,
                  seconds: totalCutSeconds(filtered),
                });
                // Apply the trim — convert candidates to silenceSegments
                s.pushHistory('Smart Trim');
                s.setSilenceSegments(
                  filtered.map((c) => ({
                    id: `trim-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
                    trackId: s.tracks[0]?.id ?? '',
                    start: c.start,
                    end: c.end,
                    durationMs: (c.end - c.start) * 1000,
                  })),
                );
                setToast({
                  message: `เจอ ${filtered.length} ช่วง รวม ${totalCutSeconds(filtered).toFixed(1)}s — กด ลบทั้งหมด เพื่อตัด`,
                  level: 'success',
                });
              } catch (err) {
                setToast({
                  message: `Smart Trim ล้มเหลว: ${err instanceof Error ? err.message : ''}`,
                  level: 'error',
                });
              } finally {
                setTrimBusy(false);
              }
            }}
            disabled={trimBusy}
            className="w-full h-8 rounded-md bg-gradient-to-r from-capcut-orange to-capcut-red hover:opacity-90 text-white text-xs font-medium flex items-center justify-center gap-1.5 disabled:opacity-60"
          >
            {trimBusy ? <Loader2 size={12} className="animate-spin" /> : <Wand2 size={12} />}
            ✂️ วิเคราะห์คำติดปาก
          </button>
          {trimSummary && (
            <div className="text-[10px] text-capcut-muted text-center">
              เจอ {trimSummary.count} ช่วง · รวม {trimSummary.seconds.toFixed(1)}s
            </div>
          )}
        </div>

        {/* V22.5 — Engagement Heatmap preview */}
        <HeatmapPreview />
      </div>
    </Section>
  );
}

/**
 * Compute + render a tiny heatmap preview for the currently selected video.
 * Reuses the loudness + scene detection results from AI Editor if available.
 */
function HeatmapPreview() {
  const assets = useEditor((s) => s.assets);
  const setToast = useEditor((s) => s.setToast);
  const [buckets, setBuckets] = useState<{ start: number; end: number; score: number }[]>([]);
  const [summary, setSummary] = useState<ReturnType<typeof summariseHeatmap> | null>(null);
  const [busy, setBusy] = useState(false);

  async function compute() {
    const video = assets.find((a) => a.kind === 'video');
    if (!video) {
      setToast({ message: 'ต้องมีวิดีโอก่อน', level: 'error' });
      return;
    }
    setBusy(true);
    try {
      const { detectScenesViaCanvas, computeLoudness } = await import('@/lib/ai/score-segments');
      const sceneChanges = await detectScenesViaCanvas(video, 0.15, 60);
      let audioBuffer: AudioBuffer | undefined;
      const audio = assets.find((a) => a.kind === 'audio');
      if (audio?.audioBuffer) audioBuffer = audio.audioBuffer;
      else if (video.audioBuffer) audioBuffer = video.audioBuffer;
      const { loudnessDb, windowStarts } = computeLoudness(audioBuffer, 0.5);
      const bk = computeHeatmap({
        duration: video.duration,
        sceneChanges,
        loudnessDb,
        rmsWindowsStart: windowStarts,
        bucketCount: 40,
      });
      setBuckets(bk.map((b) => ({ start: b.start, end: b.end, score: b.score })));
      setSummary(summariseHeatmap(bk, sceneChanges.length));
      setToast({ message: `Heatmap: ${bk.length} buckets · peak ${summariseHeatmap(bk, sceneChanges.length).peakSeconds.toFixed(1)}s`, level: 'success' });
    } catch (err) {
      setToast({
        message: `Heatmap ล้มเหลว: ${err instanceof Error ? err.message : ''}`,
        level: 'error',
      });
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="rounded-md border border-capcut-red/30 bg-capcut-red/5 p-2 space-y-2">
      <div className="flex items-center gap-1.5 text-[11px] font-semibold text-capcut-red">
        <Sparkles size={12} /> Engagement Heatmap
      </div>
      <p className="text-[10px] text-capcut-muted leading-snug">
        วิเคราะห์ scene + เสียง → แถบสีแดง/น้ำเงินแสดงความน่าสนใจ
      </p>
      <button
        type="button"
        onClick={compute}
        disabled={busy}
        className="w-full h-7 rounded-md bg-gradient-to-r from-capcut-red to-capcut-orange hover:opacity-90 text-white text-xs font-medium flex items-center justify-center gap-1.5 disabled:opacity-60"
      >
        {busy ? <Loader2 size={12} className="animate-spin" /> : <Sparkles size={12} />}
        วิเคราะห์ Heatmap
      </button>
      {buckets.length > 0 && (
        <div className="flex items-end gap-[1px] h-8 mt-1">
          {buckets.map((b, i) => (
            <div
              key={i}
              className="flex-1 rounded-sm"
              style={{
                background: `hsl(${220 - b.score * 220}, 70%, ${35 + b.score * 20}%)`,
                height: `${20 + b.score * 80}%`,
                minWidth: '2px',
              }}
              title={`${b.start.toFixed(1)}s · score ${b.score.toFixed(2)}`}
            />
          ))}
        </div>
      )}
      {summary && (
        <div className="text-[10px] text-capcut-muted space-y-0.5">
          <div>⏱ {summary.duration.toFixed(1)}s · avg {summary.averageScore.toFixed(2)}</div>
          <div>🔥 peak {summary.peakSeconds.toFixed(1)}s · quiet {summary.quietSeconds.toFixed(1)}s</div>
        </div>
      )}
    </div>
  );
}

function phaseLabel(p: Phase): string {
  switch (p) {
    case 'scenes':
      return 'ตรวจจับฉาก';
    case 'loudness':
      return 'วิเคราะห์เสียง';
    case 'scoring':
      return 'ให้คะแนน';
    case 'done':
      return 'เสร็จสิ้น';
    default:
      return 'พร้อม';
  }
}