// Left-side label panel for a single track: name, mute/volume, delete,
// mini waveform preview (audio tracks only).

'use client';

import { useEffect, useMemo, useState } from 'react';
import { Volume2, VolumeX, Trash2, Sparkles } from 'lucide-react';
import type { Track, MediaAsset } from '@/types';
import { TRACK_HEIGHT } from './constants';
import { useEditor } from '@/store/editor';
import { MiniWaveform } from '@/components/MiniWaveform';
import { usePeaks } from '@/lib/hooks/usePeaks';
import { getCachedPeaks, getOrComputePeaks } from '@/lib/audio/waveform-peaks';
import { hashSeed, ghostBuckets } from './ghost-waveform-seed';

function GhostLine({ track }: { track: Track }) {
  const buckets = useMemo(() => {
    return ghostBuckets(hashSeed(track.id), 32);
  }, [track.id]);
  const half = 6;
  const xStep = 120 / buckets.length;
  const color = track.kind === 'video' ? '#3aa6ff' : '#ff8a3d';
  const topPts: string[] = [];
  const botPts: string[] = [];
  for (let i = 0; i < buckets.length; i++) {
    const x = (i * xStep).toFixed(2);
    topPts.push(`${x},${(half - buckets[i] * (half - 1)).toFixed(2)}`);
    botPts.push(`${x},${(half + buckets[i] * (half - 1)).toFixed(2)}`);
  }
  return (
    <svg width={120} height={12} viewBox="0 0 120 12" preserveAspectRatio="none" className="block opacity-60">
      <path d={`M0,${half} L${topPts.join(' L')} L120,${half} Z`} fill={color} fillOpacity={0.45} />
      <path d={`M0,${half} L${botPts.join(' L')} L120,${half} Z`} fill={color} fillOpacity={0.45} />
      <line x1={0} y1={half} x2={120} y2={half} stroke={color} strokeOpacity={0.2} strokeWidth={0.5} vectorEffect="non-scaling-stroke" />
    </svg>
  );
}

interface Props {
  track: Track;
  onRemove: () => void;
  onUpdate: (id: string, patch: Partial<Track>) => void;
}

export function TrackLabel({ track, onRemove, onUpdate }: Props) {
  const [editing, setEditing] = useState(false);
  const [name, setName] = useState(track.name);

  useEffect(() => setName(track.name), [track.name]);

  // First audio asset on this track (for waveform preview).
  const assets = useEditor((s) => s.assets);
  const clips = useEditor((s) => s.clips);
  const firstClip = useMemo(
    () => clips.find((c) => c.trackId === track.id) ?? null,
    [clips, track.id],
  );
  const audioAsset: MediaAsset | null = useMemo(() => {
    if (track.kind !== 'audio' || !firstClip) return null;
    return assets.find((a) => a.id === firstClip.assetId) ?? null;
  }, [track.kind, firstClip, assets]);

  // Reconstruct the source Blob from the asset's object URL so we can feed
  // it into computeWaveformPeaks on demand. We only do this once per asset.
  const [peaksSource, setPeaksSource] = useState<Blob | null>(null);
  useEffect(() => {
    if (!audioAsset) {
      setPeaksSource(null);
      return;
    }
    // Try cache first.
    const cached = getCachedPeaks(audioAsset.id);
    if (cached) {
      setPeaksSource(new Blob()); // sentinel — we already have peaks
      return;
    }
    let cancelled = false;
    (async () => {
      try {
        const resp = await fetch(audioAsset.url);
        const blob = await resp.blob();
        if (cancelled) return;
        setPeaksSource(blob);
      } catch {
        /* ignore */
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [audioAsset]);

  // Trigger compute if not cached.
  useEffect(() => {
    if (!audioAsset || !peaksSource || peaksSource.size === 0) return;
    const cached = getCachedPeaks(audioAsset.id);
    if (cached) return;
    void getOrComputePeaks(audioAsset.id, peaksSource);
  }, [audioAsset, peaksSource]);

  const peaks = usePeaks(audioAsset?.id, peaksSource, !!audioAsset);

  return (
    <div
      className="border-b border-capcut-border/50 flex items-center px-2 gap-1 bg-capcut-dark"
      style={{ height: TRACK_HEIGHT }}
    >
      <div className={`w-1 h-8 rounded-sm ${track.kind === 'video' ? 'bg-capcut-blue' : 'bg-capcut-orange'}`} />
      <div className="flex-1 min-w-0">
        {track.kind === 'video' && track.videoPosition && track.videoPosition !== 'full' && (
          <span
            className="inline-block text-[9px] text-capcut-muted mr-1"
            title={`ตำแหน่ง: ${track.videoPosition}${track.videoScale ? ` · ${Math.round(track.videoScale * 100)}%` : ''}`}
          >
            {track.videoPosition === 'pip-tl' ? '◱' :
             track.videoPosition === 'pip-tr' ? '◲' :
             track.videoPosition === 'pip-bl' ? '◰' :
             track.videoPosition === 'pip-br' ? '◳' :
             track.videoPosition === 'pip-c' ? '◈' : ''}
          </span>
        )}
        {editing ? (
          <input
            autoFocus
            value={name}
            onChange={(e) => setName(e.target.value)}
            onBlur={() => {
              onUpdate(track.id, { name });
              setEditing(false);
            }}
            onKeyDown={(e) => {
              if (e.key === 'Enter') {
                onUpdate(track.id, { name });
                setEditing(false);
              } else if (e.key === 'Escape') {
                setName(track.name);
                setEditing(false);
              }
            }}
            className="w-full bg-capcut-surface border border-capcut-border rounded px-1 py-0.5 text-xs"
          />
        ) : (
          <button
            type="button"
            onClick={() => setEditing(true)}
            className="w-full text-left text-xs truncate hover:text-capcut-blue"
            title="คลิกเพื่อแก้ไขชื่อ"
          >
            {track.name}
          </button>
        )}
        {track.kind === 'audio' && (
          <div className="flex items-center gap-1 mt-0.5">
            <button
              type="button"
              onClick={() => onUpdate(track.id, { muted: !track.muted })}
              className="w-4 h-4 flex items-center justify-center text-capcut-muted hover:text-capcut-text"
              data-tip={track.muted ? 'เปิดเสียง' : 'ปิดเสียง'}
            >
              {track.muted ? <VolumeX size={10} /> : <Volume2 size={10} />}
            </button>
            <input
              type="range"
              min={0}
              max={1.5}
              step={0.01}
              value={track.volume}
              onChange={(e) => onUpdate(track.id, { volume: Number(e.target.value) })}
              className="flex-1 h-3"
              title={`ระดับเสียง ${Math.round(track.volume * 100)}%`}
            />
            <span className="text-[9px] text-capcut-muted w-6 text-right">{Math.round(track.volume * 100)}</span>
            {track.noiseReduction?.enabled && (
              <span
                className="text-capcut-blue"
                data-tip={`ตัดเสียงรบกวน ${Math.round(track.noiseReduction.amount * 100)}%`}
              >
                <Sparkles size={10} />
              </span>
            )}
          </div>
        )}
        {/* Mini waveform preview (audio/video tracks) */}
        <div className="mt-0.5 h-3 flex items-center" title={peaks ? 'ภาพรวม waveform ของแทร็ก' : 'ยังไม่มีสื่อในแทร็ก'}>
          {peaks ? (
            <MiniWaveform peaks={peaks} width={120} height={12} color={track.kind === 'audio' ? '#ff8a3d' : '#3aa6ff'} />
          ) : (
            <GhostLine track={track} />
          )}
        </div>
      </div>
      <button
        type="button"
        onClick={onRemove}
        className="w-5 h-5 rounded hover:bg-capcut-surface flex items-center justify-center text-capcut-muted hover:text-capcut-red"
        data-tip="ลบแทร็ก"
      >
        <Trash2 size={10} />
      </button>
    </div>
  );
}