'use client';

import { useCallback, useRef, useState } from 'react';
import { Upload, FileVideo, FileAudio, Trash2, Plus, FilePlus, Sparkles } from 'lucide-react';
import { useEditor } from '@/store/editor';
import { decodeAudioFile } from '@/lib/audio';
import type { MediaAsset } from '@/types';
import { formatTimeShort } from '@/lib/media';

// Demo content bundled in /public/test-media/ — loaded by the "Load sample"
// button when the media library is empty so first-time users can try the
// editor without having to find a video on disk.
const DEMO_VIDEO_URL = '/test-media/test-video.mp4';
const DEMO_AUDIO_URL = '/test-media/test-audio-with-silence.wav';
const DEMO_SRT_URL = '/test-media/test-subtitles.srt';

const ACCEPTED_VIDEO = ['video/mp4', 'video/quicktime', 'video/webm', 'video/ogg'];
const ACCEPTED_AUDIO = ['audio/mpeg', 'audio/mp3', 'audio/wav', 'audio/x-wav', 'audio/m4a', 'audio/x-m4a', 'audio/mp4', 'audio/aac', 'audio/ogg'];
const ACCEPTED_IMAGE = ['image/png', 'image/jpeg', 'image/webp', 'image/gif', 'image/svg+xml'];

function inferKind(file: File): 'video' | 'audio' | 'image' | null {
  if (ACCEPTED_VIDEO.includes(file.type)) return 'video';
  if (ACCEPTED_AUDIO.includes(file.type)) return 'audio';
  if (ACCEPTED_IMAGE.includes(file.type)) return 'image';
  // fallback by extension
  const lower = file.name.toLowerCase();
  if (/\.(mp4|mov|webm|mkv)$/.test(lower)) return 'video';
  if (/\.(mp3|wav|m4a|aac|ogg|flac)$/.test(lower)) return 'audio';
  if (/\.(png|jpg|jpeg|webp|gif|svg)$/.test(lower)) return 'image';
  return null;
}

async function probeAsset(file: File, kind: 'video' | 'audio' | 'image'): Promise<MediaAsset> {
  const url = URL.createObjectURL(file);
  const id = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}`;
  let duration = 0;
  let width: number | undefined;
  let height: number | undefined;
  let audioBuffer: AudioBuffer | undefined;

  if (kind === 'video') {
    const v = document.createElement('video');
    v.preload = 'metadata';
    v.src = url;
    await new Promise<void>((resolve, reject) => {
      v.onloadedmetadata = () => resolve();
      v.onerror = () => reject(new Error('ไม่สามารถอ่านข้อมูลวิดีโอได้'));
    });
    duration = v.duration;
    width = v.videoWidth;
    height = v.videoHeight;
    // Try to decode audio for waveform + silence detection
    try {
      const audioFile = await fetch(url).then((r) => r.blob()).then((b) => new File([b], file.name, { type: file.type }));
      audioBuffer = await decodeAudioFile(audioFile);
    } catch {
      audioBuffer = undefined;
    }
  } else if (kind === 'image') {
    const img = new Image();
    img.src = url;
    await new Promise<void>((resolve, reject) => {
      img.onload = () => resolve();
      img.onerror = () => reject(new Error('ไม่สามารถอ่านภาพได้'));
    });
    duration = 5; // default 5s for images
    width = img.naturalWidth;
    height = img.naturalHeight;
  } else {
    audioBuffer = await decodeAudioFile(file);
    duration = audioBuffer.duration;
  }

  return {
    id,
    name: file.name,
    kind,
    url,
    size: file.size,
    duration,
    width,
    height,
    audioBuffer,
  };
}

export function MediaLibrary() {
  const assets = useEditor((s) => s.assets);
  const addAsset = useEditor((s) => s.addAsset);
  const removeAsset = useEditor((s) => s.removeAsset);
  const setToast = useEditor((s) => s.setToast);
  const addClip = useEditor((s) => s.addClip);
  const tracks = useEditor((s) => s.tracks);
  const pushHistory = useEditor((s) => s.pushHistory);
  const [dragging, setDragging] = useState(false);
  const [busy, setBusy] = useState(false);
  const [demoBusy, setDemoBusy] = useState(false);
  const inputRef = useRef<HTMLInputElement | null>(null);

  /**
   * Fetch a sample asset from /public/test-media/, wrap it in a File so we
   * can reuse `probeAsset`, then add it to the library. We deliberately
   * reuse the user-upload pipeline to keep one code path.
   */
  async function fetchAsFile(url: string, filename: string, type: string): Promise<File> {
    const res = await fetch(url);
    const blob = await res.blob();
    return new File([blob], filename, { type });
  }

  async function loadDemoContent() {
    if (demoBusy) return;
    setDemoBusy(true);
    setToast({ message: 'กำลังโหลดตัวอย่าง...', level: 'info' });
    try {
      const videoFile = await fetchAsFile(DEMO_VIDEO_URL, 'test-video.mp4', 'video/mp4');
      const audioFile = await fetchAsFile(DEMO_AUDIO_URL, 'test-audio-with-silence.wav', 'audio/wav');

      const videoAsset = await probeAsset(videoFile, 'video');
      const audioAsset = await probeAsset(audioFile, 'audio');
      addAsset(videoAsset);
      addAsset(audioAsset);

      // Auto-drop onto the first matching track + start at playhead 0.
      // If a clip is already on the video/audio tracks, skip rather than
      // stacking duplicates that would confuse first-time users.
      const s = useEditor.getState();
      const existing = new Set(s.clips.map((c) => `${c.assetId}-${c.trackId}`));
      const videoTrack = tracks.find((t) => t.kind === 'video');
      const audioTrack = tracks.find((t) => t.kind === 'audio');
      let placed = 0;
      if (videoTrack && !existing.has(`${videoAsset.id}-${videoTrack.id}`)) {
        addClip({ assetId: videoAsset.id, trackId: videoTrack.id, start: 0, duration: videoAsset.duration, sourceIn: 0 });
        placed++;
      }
      if (audioTrack && !existing.has(`${audioAsset.id}-${audioTrack.id}`)) {
        addClip({ assetId: audioAsset.id, trackId: audioTrack.id, start: 0, duration: audioAsset.duration, sourceIn: 0 });
        placed++;
      }
      if (placed > 0) pushHistory('โหลดตัวอย่าง');
      setToast({
        message: `โหลดตัวอย่างสำเร็จ · ลองกด "ตรวจจับช่วงเงียบ" บนแทร็กเสียง`,
        level: 'success',
      });
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'โหลดตัวอย่างไม่สำเร็จ';
      setToast({ message: `โหลดตัวอย่างไม่สำเร็จ: ${msg}`, level: 'error' });
    } finally {
      setDemoBusy(false);
    }
  }

  const handleFiles = useCallback(
    async (files: FileList | File[]) => {
      setBusy(true);
      let added = 0;
      for (const file of Array.from(files)) {
        const kind = inferKind(file);
        if (!kind) {
          setToast({ message: `ไม่รองรับไฟล์: ${file.name}`, level: 'error' });
          continue;
        }
        try {
          const asset = await probeAsset(file, kind);
          addAsset(asset);
          added++;
        } catch (err) {
          const msg = err instanceof Error ? err.message : 'ไม่สามารถอ่านไฟล์ได้';
          setToast({ message: `${file.name}: ${msg}`, level: 'error' });
        }
      }
      if (added > 0) setToast({ message: `เพิ่มสื่อ ${added} ไฟล์`, level: 'success' });
      setBusy(false);
    },
    [addAsset, setToast],
  );

  return (
    <div className="flex-1 flex flex-col overflow-hidden">
      <div className="px-4 py-3 border-b border-capcut-border bg-gradient-to-b from-capcut-panel/50 to-transparent">
        <div className="flex items-center justify-between">
          <h2 className="text-[11px] font-bold uppercase tracking-[0.12em] text-capcut-muted flex items-center gap-2">
            <span className="w-1.5 h-1.5 rounded-full bg-capcut-blue animate-pulse-soft" />
            ไลบรารีสื่อ
          </h2>
          <span className="text-[11px] font-mono text-capcut-muted bg-capcut-surface px-1.5 py-0.5 rounded">
            {assets.length}
          </span>
        </div>
      </div>

      <div
        className={`m-3 border-2 border-dashed rounded-xl p-5 text-center transition-base ${
          dragging
            ? 'border-capcut-blue bg-capcut-blue/10 scale-[1.02] shadow-glow-blue'
            : 'border-capcut-border hover:border-capcut-blue/40 hover:bg-capcut-blue/5'
        }`}
        onDragEnter={(e) => {
          e.preventDefault();
          setDragging(true);
        }}
        onDragLeave={() => setDragging(false)}
        onDragOver={(e) => e.preventDefault()}
        onDrop={(e) => {
          e.preventDefault();
          setDragging(false);
          if (e.dataTransfer.files) handleFiles(e.dataTransfer.files);
        }}
      >
        <div className={`mx-auto mb-3 w-12 h-12 rounded-full flex items-center justify-center transition-base ${
          dragging ? 'bg-capcut-blue/20' : 'bg-capcut-surface'
        }`}>
          <Upload size={22} className={dragging ? 'text-capcut-blue' : 'text-capcut-muted'} />
        </div>
        <p className="text-sm text-capcut-text">ลากไฟล์มาวางที่นี่</p>
        <p className="text-xs text-capcut-muted mt-1">mp4 / mov / webm · png / jpg · mp3 / wav / m4a</p>
        <button
          type="button"
          onClick={() => inputRef.current?.click()}
          disabled={busy}
          className="mt-3 px-3.5 py-2 text-xs rounded-lg bg-gradient-to-b from-capcut-blue to-capcut-blueDark hover:from-capcut-blueLight hover:to-capcut-blue text-white font-medium flex items-center gap-1.5 mx-auto disabled:opacity-50 shadow-soft border border-capcut-blue/40"
        >
          <FilePlus size={14} /> เลือกไฟล์
        </button>
        {assets.length === 0 && (
          <button
            type="button"
            onClick={loadDemoContent}
            disabled={demoBusy || busy}
            className="mt-2 px-3 py-1.5 text-xs rounded-lg bg-capcut-orange/15 hover:bg-capcut-orange/25 text-capcut-orange flex items-center gap-1.5 mx-auto disabled:opacity-50 border border-capcut-orange/40 font-medium shadow-glow-orange"
            data-tip="โหลดวิดีโอ+เสียงตัวอย่าง พร้อม auto-drop ลง timeline"
          >
            <Sparkles size={14} /> {demoBusy ? 'กำลังโหลด...' : 'โหลดตัวอย่าง 1 คลิก'}
          </button>
        )}
        {assets.length > 0 && assets.length < 3 && (
          <button
            type="button"
            onClick={loadDemoContent}
            disabled={demoBusy || busy}
            className="mt-2 px-2 py-1 text-[11px] rounded border border-capcut-border text-capcut-muted hover:text-capcut-orange hover:border-capcut-orange/40 flex items-center gap-1 mx-auto disabled:opacity-50"
            data-tip="เพิ่มไฟล์ตัวอย่างเข้าไลบรารี"
          >
            <Sparkles size={11} /> เพิ่มตัวอย่าง
          </button>
        )}
        <input
          ref={inputRef}
          type="file"
          multiple
          accept="video/*,audio/*,image/*"
          className="hidden"
          onChange={(e) => {
            if (e.target.files) handleFiles(e.target.files);
            e.target.value = '';
          }}
        />
      </div>

      <div className="flex-1 overflow-y-auto px-2 pb-3 space-y-1.5 scroll-thin">
        {assets.map((asset) => (
          <div
            key={asset.id}
            className="group relative flex items-center gap-2.5 px-2.5 py-2 rounded-lg hover:bg-capcut-surface cursor-grab active:cursor-grabbing border border-transparent hover:border-capcut-border transition-base animate-slide-up"
            draggable
            onDragStart={(e) => {
              e.dataTransfer.setData('application/x-capcut-asset', asset.id);
              e.dataTransfer.effectAllowed = 'copy';
            }}
            title={`${asset.name} · ${formatTimeShort(asset.duration)}`}
          >
            <div className="w-11 h-11 rounded-lg bg-gradient-to-br from-capcut-surface to-capcut-panel flex items-center justify-center shrink-0 overflow-hidden ring-1 ring-capcut-border/50 group-hover:ring-capcut-blue/40 transition-base">
              {asset.kind === 'video' ? (
                <FileVideo size={18} className="text-capcut-blue" />
              ) : asset.kind === 'image' ? (
                <img src={asset.url} alt="" className="w-full h-full object-cover" />
              ) : (
                <FileAudio size={18} className="text-capcut-orange" />
              )}
            </div>
            <div className="flex-1 min-w-0">
              <div className="text-xs font-medium truncate text-capcut-text">{asset.name}</div>
              <div className="text-[10px] text-capcut-muted flex items-center gap-1.5 mt-0.5">
                <span className="bg-capcut-surface px-1 rounded text-[9px] font-mono">{asset.kind}</span>
                <span>·</span>
                <span>{formatTimeShort(asset.duration)}</span>
                {asset.width && asset.height ? (
                  <span>
                    {asset.width}×{asset.height}
                  </span>
                ) : null}
              </div>
            </div>
            <button
              type="button"
              onClick={(e) => {
                e.stopPropagation();
                removeAsset(asset.id);
              }}
              className="opacity-0 group-hover:opacity-100 w-7 h-7 rounded hover:bg-capcut-border text-capcut-muted hover:text-capcut-red flex items-center justify-center"
              data-tip="ลบออกจากไลบรารี"
            >
              <Trash2 size={13} />
            </button>
          </div>
        ))}
        {assets.length === 0 && !busy && (
          <p className="text-center text-xs text-capcut-muted mt-6">ยังไม่มีสื่อ — เริ่มด้วยการอัปโหลด</p>
        )}
        {busy && (
          <p className="text-center text-xs text-capcut-blue mt-2 animate-pulse-soft">กำลังประมวลผลไฟล์…</p>
        )}
      </div>
    </div>
  );
}