(function () {
  'use strict';

  const tk = {
    bgPage: '#0f0f0f', bgCard: '#1a1a1a', bgCardAlt: '#141414', bgInput: '#111',
    bgHover: '#222', bgSunken: '#0a0a0a', bgOverlay: 'rgba(0,0,0,0.75)',
    border: '#2a2a2a', borderSubtle: '#1e1e1e',
    textPrimary: '#f5f5f5', textSecondary: '#aaaaaa', textMuted: '#666',
    textDisabled: '#444', accent: '#00ff00', accentText: '#000',
    error: '#ff4444',
  };

  const CURVE_CHANNELS = [
    { id: 'master', label: 'RGB', color: '#ffffff' },
    { id: 'r', label: 'R', color: '#ff5555' },
    { id: 'g', label: 'G', color: '#55ee55' },
    { id: 'b', label: 'B', color: '#5599ff' },
  ];

  const CURVE_SVG_SIZE = 256;
  const POINT_RADIUS = 4;
  const HIT_RADIUS = 10;

  function makeDefaultCurves() {
    return { master: [{ x: 0, y: 0 }, { x: 1, y: 1 }], r: [{ x: 0, y: 0 }, { x: 1, y: 1 }], g: [{ x: 0, y: 0 }, { x: 1, y: 1 }], b: [{ x: 0, y: 0 }, { x: 1, y: 1 }] };
  }

  function catmullRomPath(points, size) {
    if (!points || points.length < 2) return '';
    const pts = points.map(p => ({ x: p.x * size, y: (1 - p.y) * size }));
    if (pts.length === 2) return `M ${pts[0].x.toFixed(2)},${pts[0].y.toFixed(2)} L ${pts[1].x.toFixed(2)},${pts[1].y.toFixed(2)}`;
    let d = `M ${pts[0].x.toFixed(2)},${pts[0].y.toFixed(2)}`;
    for (let i = 0; i < pts.length - 1; i++) {
      const p0 = pts[Math.max(0, i - 1)], p1 = pts[i], p2 = pts[i + 1], p3 = pts[Math.min(pts.length - 1, i + 2)];
      const cp1x = p1.x + (p2.x - p0.x) / 6, cp1y = p1.y + (p2.y - p0.y) / 6;
      const cp2x = p2.x - (p3.x - p1.x) / 6, cp2y = p2.y - (p3.y - p1.y) / 6;
      d += ` C ${cp1x.toFixed(2)},${cp1y.toFixed(2)} ${cp2x.toFixed(2)},${cp2y.toFixed(2)} ${p2.x.toFixed(2)},${p2.y.toFixed(2)}`;
    }
    return d;
  }

  function CurveEditor({ curves, onCurvesChange }) {
    const [activeChannel, setActiveChannel] = React.useState('master');
    const svgRef = React.useRef(null);
    const currentPoints = curves[activeChannel];
    const channelColor = CURVE_CHANNELS.find(c => c.id === activeChannel)?.color || '#ffffff';
    const S = CURVE_SVG_SIZE;
    const gridVals = [0.25, 0.5, 0.75];

    function getSvgNorm(clientX, clientY) {
      const rect = svgRef.current.getBoundingClientRect();
      return {
        x: Math.max(0, Math.min(1, (clientX - rect.left) / rect.width)),
        y: Math.max(0, Math.min(1, 1 - (clientY - rect.top) / rect.height)),
      };
    }

    function handleSvgClick(e) {
      const norm = getSvgNorm(e.clientX, e.clientY);
      for (const pt of currentPoints) {
        const dx = (pt.x - norm.x) * S, dy = (pt.y - norm.y) * S;
        if (Math.sqrt(dx * dx + dy * dy) <= HIT_RADIUS * 1.5) return;
      }
      const newPoints = [...currentPoints, norm].sort((a, b) => a.x - b.x);
      onCurvesChange({ ...curves, [activeChannel]: newPoints });
    }

    function handlePointMouseDown(e, index) {
      e.stopPropagation(); e.preventDefault();
      const dragPoints = currentPoints.map(p => ({ ...p }));
      function onMouseMove(ev) {
        const norm = getSvgNorm(ev.clientX, ev.clientY);
        if (index === 0) dragPoints[index] = { x: 0, y: norm.y };
        else if (index === dragPoints.length - 1) dragPoints[index] = { x: 1, y: norm.y };
        else { const minX = dragPoints[index-1].x+0.005, maxX = dragPoints[index+1].x-0.005; dragPoints[index] = { x: Math.max(minX, Math.min(maxX, norm.x)), y: norm.y }; }
        onCurvesChange({ ...curves, [activeChannel]: [...dragPoints] });
      }
      function onMouseUp() { window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); }
      window.addEventListener('mousemove', onMouseMove);
      window.addEventListener('mouseup', onMouseUp);
    }

    function handlePointDoubleClick(e, index) {
      e.stopPropagation();
      if (index === 0 || index === currentPoints.length - 1) return;
      onCurvesChange({ ...curves, [activeChannel]: currentPoints.filter((_, i) => i !== index) });
    }

    return (
      <div>
        <div style={{ display: 'flex', alignItems: 'center', gap: '4px', marginBottom: '8px' }}>
          {CURVE_CHANNELS.map(ch => (
            <button key={ch.id} onClick={() => setActiveChannel(ch.id)} style={{ padding: '3px 10px', backgroundColor: activeChannel === ch.id ? tk.border : 'transparent', color: activeChannel === ch.id ? ch.color : tk.textMuted, border: `1px solid ${activeChannel === ch.id ? ch.color : tk.border}`, borderRadius: '3px', cursor: 'pointer', fontSize: '11px', fontWeight: '600' }}>
              {ch.label}
            </button>
          ))}
          <button onClick={() => onCurvesChange({ ...curves, [activeChannel]: [{ x: 0, y: 0 }, { x: 1, y: 1 }] })} style={{ marginLeft: 'auto', padding: '3px 10px', backgroundColor: 'transparent', color: tk.textMuted, border: `1px solid ${tk.border}`, borderRadius: '3px', cursor: 'pointer', fontSize: '11px' }}>Reset</button>
        </div>
        <svg ref={svgRef} viewBox={`0 0 ${S} ${S}`} onClick={handleSvgClick} style={{ display: 'block', width: '100%', height: 'auto', backgroundColor: tk.bgCard, borderRadius: '4px', cursor: 'crosshair', userSelect: 'none' }}>
          {gridVals.map(v => (
            <g key={v}>
              <line x1={v*S} y1={0} x2={v*S} y2={S} stroke={tk.border} strokeWidth="1" />
              <line x1={0} y1={v*S} x2={S} y2={v*S} stroke={tk.border} strokeWidth="1" />
            </g>
          ))}
          <line x1={0} y1={S} x2={S} y2={0} stroke={tk.border} strokeWidth="1" strokeDasharray="5,5" />
          <path d={catmullRomPath(currentPoints, S)} fill="none" stroke={channelColor} strokeWidth="1.5" />
          {currentPoints.map((pt, i) => (
            <circle key={i} cx={pt.x*S} cy={(1-pt.y)*S} r={POINT_RADIUS} fill={channelColor} stroke={tk.bgInput} strokeWidth="1.5" style={{ cursor: 'grab' }} onMouseDown={(e) => handlePointMouseDown(e, i)} onDoubleClick={(e) => handlePointDoubleClick(e, i)} />
          ))}
        </svg>
        <div style={{ fontSize: '10px', color: tk.textMuted, marginTop: '5px', textAlign: 'center' }}>Click to add · Double-click to remove · Drag to adjust</div>
      </div>
    );
  }

  function ColorWheel({ label, offsetRed, offsetGreen, offsetBlue, onOffsetChange }) {
    const SIZE = 120;
    const cx = SIZE / 2, cy = SIZE / 2, r = SIZE / 2 - 8;
    const dotX = cx + (offsetRed - offsetBlue) * r * 0.5;
    const dotY = cy - (offsetGreen - (offsetRed + offsetBlue) / 2) * r * 0.5;
    const clampedDotX = Math.max(cx - r, Math.min(cx + r, dotX));
    const clampedDotY = Math.max(cy - r, Math.min(cy + r, dotY));

    return (
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
        <div style={{ fontSize: 10, color: tk.textMuted, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em' }}>{label}</div>
        <svg width={SIZE} height={SIZE} style={{ display: 'block', cursor: 'crosshair' }}>
          <defs>
            <radialGradient id={`cw-${label}-bg`} cx="50%" cy="50%" r="50%">
              <stop offset="0%" stopColor="#888888" />
              <stop offset="100%" stopColor="#222" />
            </radialGradient>
          </defs>
          <circle cx={cx} cy={cy} r={r} fill={`url(#cw-${label}-bg)`} stroke={tk.border} strokeWidth="1" />
          <line x1={cx-r} y1={cy} x2={cx+r} y2={cy} stroke="rgba(255,255,255,0.1)" strokeWidth="0.5" />
          <line x1={cx} y1={cy-r} x2={cx} y2={cy+r} stroke="rgba(255,255,255,0.1)" strokeWidth="0.5" />
          <circle cx={clampedDotX} cy={clampedDotY} r={4} fill="#fff" stroke="#000" strokeWidth="1.5" />
        </svg>
        <div style={{ display: 'flex', gap: 4, alignItems: 'center', justifyContent: 'center', width: SIZE }}>
          {[['R', offsetRed, '#ff5555', v => onOffsetChange(v, offsetGreen, offsetBlue)],
            ['G', offsetGreen, '#55ee55', v => onOffsetChange(offsetRed, v, offsetBlue)],
            ['B', offsetBlue, '#5599ff', v => onOffsetChange(offsetRed, offsetGreen, v)]].map(([lab, val, col, setter]) => (
            <div key={lab} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', flex: 1 }}>
              <span style={{ fontSize: 9, color: col }}>{lab}</span>
              <input type="number" value={val.toFixed(2)} min={-1} max={1} step={0.01} onChange={e => setter(parseFloat(e.target.value) || 0)} style={{ width: '100%', background: tk.bgInput, border: `1px solid ${tk.border}`, borderRadius: 3, color: tk.textPrimary, fontSize: 9, textAlign: 'center', padding: '1px 2px' }} />
            </div>
          ))}
        </div>
      </div>
    );
  }

  const PRESET_LUTS = [
    { id: 'cinematic_teal_orange', label: 'Cinematic' },
    { id: 'bw', label: 'B&W' },
    { id: 'warm', label: 'Warm' },
    { id: 'cool', label: 'Cool' },
    { id: 'fade', label: 'Fade' },
  ];

  function ColorGradingPanelReal() {
    const [clips, setClips] = React.useState([{
      id: 'demo-clip-1',
      name: 'Interview.mp4',
      colorGrading: {
        lift: { r: 0, g: 0, b: 0 },
        gamma: { r: 0, g: 0, b: 0 },
        gain: { r: 0, g: 0, b: 0 },
        saturation: 1,
        contrast: 1,
        temperature: 0,
        tint: 0,
        curves: null,
        luts: [],
      },
    }]);
    const [activeTab, setActiveTab] = React.useState('wheels');
    const [curves, setCurves] = React.useState(makeDefaultCurves());
    const [selectedLutId, setSelectedLutId] = React.useState(null);
    const setGlobalColorGrading = () => {};

    const updateClip = (id, patch) => setClips(prev => prev.map(c => c.id === id ? { ...c, ...patch } : c));
    const selectedClip = clips[0];
    const cg = selectedClip.colorGrading;

    const handleLutImport = () => alert('LUT import requires the desktop app.');

    const updateCG = (patch) => {
      updateClip(selectedClip.id, { colorGrading: { ...cg, ...patch } });
    };

    const Slider = ({ label, value, min, max, step, onChange, unit = '' }) => (
      <div style={{ marginBottom: 10 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, color: tk.textMuted, marginBottom: 2 }}>
          <span>{label}</span>
          <span style={{ color: tk.textSecondary }}>{typeof value === 'number' ? (step < 0.01 ? value.toFixed(3) : step < 1 ? value.toFixed(2) : value) : value}{unit}</span>
        </div>
        <input type="range" min={min} max={max} step={step} value={value} onChange={e => onChange(Number(e.target.value))} style={{ width: '100%', accentColor: '#00ff00', cursor: 'pointer' }} />
      </div>
    );

    const css = `
      .vls-ed-cgp { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: ${tk.bgCard}; color: ${tk.textPrimary}; display: flex; flex-direction: column; }
      .vls-ed-cgp-tabs { display: flex; border-bottom: 1px solid ${tk.border}; background: ${tk.bgCardAlt}; }
      .vls-ed-cgp-tab { flex: 1; padding: 9px 4px; background: transparent; border: none; border-bottom: 2px solid transparent; color: ${tk.textMuted}; font-size: 11px; font-weight: 600; text-transform: uppercase; cursor: pointer; }
      .vls-ed-cgp-tab.active { background: ${tk.bgCard}; border-bottom-color: ${tk.accent}; color: ${tk.accent}; }
      .vls-ed-cgp-body { padding: 14px; overflow-y: auto; }
    `;

    return (
      <div className="vls-ed-cgp">
        <style>{css}</style>
        <div style={{ padding: '10px 14px', borderBottom: `1px solid ${tk.border}`, fontSize: 13, fontWeight: 700, color: tk.accent }}>Color Grading</div>
        <div className="vls-ed-cgp-tabs">
          {['wheels', 'curves', 'scopes', 'luts'].map(tab => (
            <button key={tab} className={`vls-ed-cgp-tab${activeTab === tab ? ' active' : ''}`} onClick={() => setActiveTab(tab)}>{tab}</button>
          ))}
        </div>
        <div className="vls-ed-cgp-body">
          {/* Color Wheels Tab */}
          {activeTab === 'wheels' && (
            <div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10, marginBottom: 16 }}>
                <ColorWheel label="Lift" offsetRed={cg.lift?.r ?? 0} offsetGreen={cg.lift?.g ?? 0} offsetBlue={cg.lift?.b ?? 0} onOffsetChange={(r,g,b) => updateCG({ lift: { r,g,b } })} />
                <ColorWheel label="Gamma" offsetRed={cg.gamma?.r ?? 0} offsetGreen={cg.gamma?.g ?? 0} offsetBlue={cg.gamma?.b ?? 0} onOffsetChange={(r,g,b) => updateCG({ gamma: { r,g,b } })} />
                <ColorWheel label="Gain" offsetRed={cg.gain?.r ?? 0} offsetGreen={cg.gain?.g ?? 0} offsetBlue={cg.gain?.b ?? 0} onOffsetChange={(r,g,b) => updateCG({ gain: { r,g,b } })} />
              </div>
              <Slider label="Saturation" value={cg.saturation ?? 1} min={0} max={2} step={0.01} onChange={v => updateCG({ saturation: v })} />
              <Slider label="Contrast" value={cg.contrast ?? 1} min={0} max={2} step={0.01} onChange={v => updateCG({ contrast: v })} />
              <Slider label="Temperature" value={cg.temperature ?? 0} min={-100} max={100} step={1} onChange={v => updateCG({ temperature: v })} />
              <Slider label="Tint" value={cg.tint ?? 0} min={-100} max={100} step={1} onChange={v => updateCG({ tint: v })} />
              <button
                onClick={() => updateClip(selectedClip.id, { colorGrading: { lift:{r:0,g:0,b:0}, gamma:{r:0,g:0,b:0}, gain:{r:0,g:0,b:0}, saturation:1, contrast:1, temperature:0, tint:0, curves:null, luts:[] } })}
                style={{ padding: '6px 12px', background: tk.bgHover, border: `1px solid ${tk.border}`, borderRadius: 4, color: tk.textMuted, fontSize: 11, cursor: 'pointer', marginTop: 4 }}
              >
                Reset All
              </button>
            </div>
          )}

          {/* Curves Tab */}
          {activeTab === 'curves' && (
            <div>
              <CurveEditor curves={curves} onCurvesChange={setCurves} />
              <button onClick={() => setCurves(makeDefaultCurves())} style={{ marginTop: 10, padding: '6px 12px', background: tk.bgHover, border: `1px solid ${tk.border}`, borderRadius: 4, color: tk.textMuted, fontSize: 11, cursor: 'pointer', width: '100%' }}>
                Reset All Curves
              </button>
            </div>
          )}

          {/* Scopes Tab */}
          {activeTab === 'scopes' && (
            <div>
              <div style={{ fontSize: 12, color: tk.textMuted, marginBottom: 12, lineHeight: 1.5 }}>
                Waveform and vectorscope require a live video element.<br />
                These scopes are available in the desktop app with a real video timeline.
              </div>
              <div style={{ background: tk.bgInput, border: `1px solid ${tk.border}`, borderRadius: 6, padding: '24px', textAlign: 'center', color: tk.textDisabled, fontSize: 11 }}>
                Waveform Scope — Connect video element
              </div>
              <div style={{ background: tk.bgInput, border: `1px solid ${tk.border}`, borderRadius: 6, padding: '24px', textAlign: 'center', color: tk.textDisabled, fontSize: 11, marginTop: 8 }}>
                Vectorscope — Connect video element
              </div>
            </div>
          )}

          {/* LUTs Tab */}
          {activeTab === 'luts' && (
            <div>
              <div style={{ fontSize: 11, fontWeight: 700, color: tk.textMuted, textTransform: 'uppercase', marginBottom: 10 }}>Preset LUTs</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6, marginBottom: 16 }}>
                {PRESET_LUTS.map(lut => (
                  <button key={lut.id}
                    onClick={() => { setSelectedLutId(lut.id); console.log('[demo] apply LUT:', lut.label); }}
                    style={{ padding: '10px', background: selectedLutId === lut.id ? 'rgba(0,255,0,0.1)' : tk.bgCardAlt, border: `1px solid ${selectedLutId === lut.id ? 'rgba(0,255,0,0.4)' : tk.border}`, borderRadius: 6, color: selectedLutId === lut.id ? tk.accent : tk.textSecondary, fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>
                    {lut.label}
                  </button>
                ))}
              </div>
              <div style={{ borderTop: `1px solid ${tk.border}`, paddingTop: 14 }}>
                <div style={{ fontSize: 11, fontWeight: 700, color: tk.textMuted, textTransform: 'uppercase', marginBottom: 8 }}>Import LUT</div>
                <button onClick={handleLutImport} style={{ width: '100%', padding: '10px', background: tk.bgHover, border: `1px dashed ${tk.border}`, borderRadius: 6, color: tk.textMuted, fontSize: 12, cursor: 'pointer' }}>
                  + Import .cube / .3dl file
                </button>
                <div style={{ fontSize: 10, color: tk.textDisabled, marginTop: 6, textAlign: 'center' }}>LUT import requires the desktop app</div>
              </div>
              {selectedLutId && (
                <div style={{ marginTop: 14 }}>
                  <Slider label="LUT Intensity" value={100} min={0} max={100} step={1} onChange={() => {}} unit="%" />
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    );
  }

  window.ColorGradingPanelReal = ColorGradingPanelReal;
})();
