/**
 * VibeLoop Editor – TikTok-ähnlich: Hooks, Text, Emoji, Filter, Video & Foto.
 */
const VibeLoopEditor = (function () {
  const HOOKS = [
    'POV: Du entdeckst das hier…',
    'Wusstest du, dass…',
    'Niemand redet darüber, aber…',
    '3 Gründe warum du das brauchst',
    'So hab ich es geschafft 🔥',
    'Das musst du sehen 👀',
    'Warte bis zum Ende…',
    'Keiner erzählt dir das:',
  ];

  const EMOJIS = [
    '🔥', '❤️', '😂', '😍', '💯', '✨', '👀', '🙌', '💪', '🎉', '😎', '🤯', '💀', '🫶', '⭐', '🚀',
    '💎', '👑', '🎯', '⚡', '🍕', '🎵', '📍', '💄', '🎮', '🏋️', '🐾', '✈️', '🔧', '📚', '🚗',
    '🌹', '💋', '🥳', '🤩', '😘', '🙏', '👏', '💅', '🌈', '☀️', '🌙', '💫', '🦄', '🐶', '🐱', '🦋',
  ];

  const FILTERS = {
    none: '',
    warm: 'sepia(0.25) saturate(1.3) hue-rotate(-8deg)',
    cool: 'saturate(1.1) hue-rotate(15deg) brightness(1.05)',
    vivid: 'saturate(1.6) contrast(1.1)',
    bw: 'grayscale(1) contrast(1.05)',
    fade: 'contrast(0.9) brightness(1.08) saturate(0.85)',
  };

  let overlays = [];
  let currentFilter = 'none';
  let mediaType = 'video';
  let mediaSrc = '';
  let dragId = null;
  let dragOff = { x: 0, y: 0 };
  let onClose = null;
  let onCancel = null;
  let openOpts = null;

  const $ = (s, r) => (r || document).querySelector(s);

  function esc(s) {
    const d = document.createElement('div');
    d.textContent = s || '';
    return d.innerHTML;
  }

  function uid() {
    return 'o' + Math.random().toString(36).slice(2, 9);
  }

  function getStageRect() {
    return $('#cp-editor-stage').getBoundingClientRect();
  }

  function renderOverlaysOnStage() {
    const layer = $('#cp-editor-overlays');
    if (!layer) return;
    layer.innerHTML = '';
    overlays.forEach((o) => {
      const el = document.createElement('div');
      el.className = 'cp-overlay-item cp-overlay-' + o.kind;
      el.dataset.id = o.id;
      el.style.left = o.x + '%';
      el.style.top = o.y + '%';
      el.style.transform = 'translate(-50%,-50%) scale(' + o.scale + ') rotate(' + o.rotation + 'deg)';
      if (o.kind === 'emoji' || o.kind === 'sticker') {
        if (window.VlEmoji) {
          el.innerHTML = VlEmoji.html(o.content, 'cp-emoji-glow', Math.round(o.fontSize * 1.5));
        } else {
          el.textContent = o.content;
          el.style.fontSize = (o.fontSize * 1.4) + 'px';
        }
      } else {
        el.innerHTML = '<span style="color:' + esc(o.color) + ';font-size:' + o.fontSize + 'px;background:' +
          esc(o.bg) + '">' + esc(o.content) + '</span>';
      }
      el.onpointerdown = (e) => startDrag(e, o.id);
      layer.appendChild(el);
    });
  }

  function applyFilter() {
    const media = $('#cp-editor-media');
    if (media) media.style.filter = FILTERS[currentFilter] || '';
  }

  function startDrag(e, id) {
    e.preventDefault();
    dragId = id;
    const rect = getStageRect();
    const o = overlays.find((x) => x.id === id);
    if (!o) return;
    dragOff.x = e.clientX - rect.left - (o.x / 100) * rect.width;
    dragOff.y = e.clientY - rect.top - (o.y / 100) * rect.height;
    e.target.setPointerCapture(e.pointerId);
  }

  function onDragMove(e) {
    if (!dragId) return;
    const o = overlays.find((x) => x.id === dragId);
    const rect = getStageRect();
    if (!o || !rect.width) return;
    o.x = Math.min(98, Math.max(2, ((e.clientX - rect.left - dragOff.x) / rect.width) * 100));
    o.y = Math.min(98, Math.max(2, ((e.clientY - rect.top - dragOff.y) / rect.height) * 100));
    renderOverlaysOnStage();
  }

  function endDrag() {
    dragId = null;
  }

  function addOverlay(kind, content, opts = {}) {
    overlays.push({
      id: uid(),
      kind,
      content: content || (kind === 'emoji' ? '🔥' : 'Text'),
      x: opts.x ?? 50,
      y: opts.y ?? (kind === 'hook' ? 18 : 45),
      scale: opts.scale ?? 1,
      rotation: 0,
      color: opts.color || '#ffffff',
      bg: opts.bg || 'rgba(0,0,0,0.5)',
      fontSize: kind === 'hook' ? 22 : kind === 'emoji' ? 36 : 18,
      startSec: kind === 'hook' ? 0 : 0,
      endSec: kind === 'hook' ? 4 : 0,
    });
    renderOverlaysOnStage();
  }

  function removeSelected() {
    const sel = $('#cp-editor-selected');
    const id = sel && sel.value;
    if (!id) return;
    overlays = overlays.filter((o) => o.id !== id);
    renderOverlaysOnStage();
    refreshSelect();
  }

  function refreshSelect() {
    const sel = $('#cp-editor-selected');
    if (!sel) return;
    sel.innerHTML = '<option value="">Overlay wählen…</option>';
    overlays.forEach((o) => {
      const opt = document.createElement('option');
      opt.value = o.id;
      opt.textContent = o.kind + ': ' + (o.content || '').slice(0, 20);
      sel.appendChild(opt);
    });
  }

  function loadMedia(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => {
        mediaSrc = reader.result;
        mediaType = file.type.startsWith('video') ? 'video' : 'photo';
        const stage = $('#cp-editor-stage');
        stage.innerHTML = '';
        const wrap = document.createElement('div');
        wrap.className = 'cp-editor-media-wrap';
        wrap.id = 'cp-editor-media-wrap';
        if (mediaType === 'video') {
          const v = document.createElement('video');
          v.id = 'cp-editor-media';
          v.src = mediaSrc;
          v.playsInline = true;
          v.muted = true;
          v.loop = true;
          v.autoplay = true;
          v.onloadedmetadata = () => updateCopyrightWarn();
          wrap.appendChild(v);
        } else {
          const img = document.createElement('img');
          img.id = 'cp-editor-media';
          img.src = mediaSrc;
          img.alt = '';
          wrap.appendChild(img);
        }
        const layer = document.createElement('div');
        layer.id = 'cp-editor-overlays';
        layer.className = 'cp-editor-overlays';
        wrap.appendChild(layer);
        stage.appendChild(wrap);
        applyFilter();
        renderOverlaysOnStage();
        resolve({ mediaType, mediaSrc });
      };
      reader.onerror = reject;
      reader.readAsDataURL(file);
    });
  }

  function loadEmojiBitmap(emoji, size) {
    return new Promise((resolve, reject) => {
      if (!window.VlEmoji) {
        reject(new Error('no VlEmoji'));
        return;
      }
      const img = new Image();
      img.crossOrigin = 'anonymous';
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = VlEmoji.url(emoji, size);
    });
  }

  async function bakePhoto() {
    const media = $('#cp-editor-media');
    const wrap = $('#cp-editor-media-wrap');
    if (!media || mediaType !== 'photo') return mediaSrc;

    const rect = wrap.getBoundingClientRect();
    const w = Math.min(1080, Math.round(rect.width * 2)) || 720;
    const h = Math.round(w * (16 / 9));
    const canvas = document.createElement('canvas');
    canvas.width = w;
    canvas.height = h;
    const ctx = canvas.getContext('2d');

    const filter = FILTERS[currentFilter] || '';
    if (filter) ctx.filter = filter;

    const img = media;
    const ir = img.naturalWidth / img.naturalHeight;
    const cr = w / h;
    let dw, dh, dx, dy;
    if (ir > cr) {
      dh = h;
      dw = dh * ir;
      dx = (w - dw) / 2;
      dy = 0;
    } else {
      dw = w;
      dh = dw / ir;
      dx = 0;
      dy = (h - dh) / 2;
    }
    ctx.drawImage(img, dx, dy, dw, dh);
    ctx.filter = 'none';

    for (const o of overlays) {
      const px = (o.x / 100) * w;
      const py = (o.y / 100) * h;
      ctx.save();
      ctx.translate(px, py);
      ctx.rotate((o.rotation * Math.PI) / 180);
      ctx.scale(o.scale, o.scale);
      if (o.kind === 'emoji' || o.kind === 'sticker') {
        const es = o.fontSize * 2.4;
        try {
          const eimg = await loadEmojiBitmap(o.content, Math.round(es));
          ctx.drawImage(eimg, -es / 2, -es / 2, es, es);
        } catch (_) {
          ctx.font = (o.fontSize * 2) + 'px serif';
          ctx.textAlign = 'center';
          ctx.textBaseline = 'middle';
          ctx.fillText(o.content, 0, 0);
        }
      } else {
        ctx.font = 'bold ' + o.fontSize * 1.6 + 'px sans-serif';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        const text = o.content;
        const metrics = ctx.measureText(text);
        const pad = 12;
        ctx.fillStyle = o.bg || 'rgba(0,0,0,0.5)';
        ctx.fillRect(-metrics.width / 2 - pad, -o.fontSize, metrics.width + pad * 2, o.fontSize * 2.2);
        ctx.fillStyle = o.color || '#fff';
        ctx.fillText(text, 0, 0);
      }
      ctx.restore();
    }

    return canvas.toDataURL('image/jpeg', 0.92);
  }

  async function captureVideoThumb() {
    const v = $('#cp-editor-media');
    if (!v || mediaType !== 'video') return '';
    return new Promise((resolve) => {
      const c = document.createElement('canvas');
      c.width = 360;
      c.height = 640;
      const ctx = c.getContext('2d');
      const draw = () => {
        try {
          ctx.drawImage(v, 0, 0, c.width, c.height);
          resolve(c.toDataURL('image/jpeg', 0.85));
        } catch (_) {
          resolve('');
        }
      };
      if (v.readyState >= 2) {
        v.currentTime = Math.min(0.5, v.duration || 0.5);
        v.onseeked = draw;
        setTimeout(() => resolve(''), 2500);
      } else {
        v.onloadeddata = () => {
          v.currentTime = 0.3;
          v.onseeked = draw;
        };
        setTimeout(() => resolve(''), 2500);
      }
    });
  }

  function buildShell() {
    if ($('#cp-editor-screen')) return;
    const el = document.createElement('div');
    el.id = 'cp-editor-screen';
    el.className = 'hidden';
    el.innerHTML =
      '<div class="cp-editor-top">' +
      '<button type="button" id="cp-editor-cancel" class="btn-ghost">✕</button>' +
      '<span>Editor</span>' +
      '<button type="button" id="cp-editor-post" class="btn-primary cp-editor-post-btn">Posten</button>' +
      '</div>' +
      '<div id="cp-editor-stage" class="cp-editor-stage"></div>' +
      '<div class="cp-editor-tools">' +
      '<div class="cp-editor-tabs">' +
      '<button type="button" data-tool="hook" class="active">🎣 Hook</button>' +
      '<button type="button" data-tool="text">📝 Text</button>' +
      '<button type="button" data-tool="emoji">😀 Emoji</button>' +
      '<button type="button" data-tool="filter">✨ Filter</button>' +
      '</div>' +
      '<div id="cp-editor-panel-hook" class="cp-editor-panel">' +
      '<div id="cp-hook-list" class="cp-hook-list"></div>' +
      '<input id="cp-hook-custom" placeholder="Eigener Hook…" maxlength="120">' +
      '<button type="button" id="cp-hook-add" class="btn-primary">Hook einfügen</button>' +
      '</div>' +
      '<div id="cp-editor-panel-text" class="cp-editor-panel hidden">' +
      '<input id="cp-text-input" placeholder="Text auf Video…" maxlength="120">' +
      '<button type="button" id="cp-text-add" class="btn-primary">Text einfügen</button>' +
      '</div>' +
      '<div id="cp-editor-panel-emoji" class="cp-editor-panel hidden">' +
      '<div id="cp-emoji-grid" class="cp-emoji-grid"></div>' +
      '</div>' +
      '<div id="cp-editor-panel-filter" class="cp-editor-panel hidden">' +
      '<div id="cp-filter-grid" class="cp-filter-grid"></div>' +
      '</div>' +
      '<div class="cp-editor-edit-row">' +
      '<select id="cp-editor-selected"></select>' +
      '<button type="button" id="cp-editor-delete" class="btn-ghost">🗑</button>' +
      '</div>' +
      '<div id="cp-editor-copyright" class="cp-editor-copyright">' +
      '<p><strong>Community:</strong> Keine Hassrede, Mobbing oder Drohungen.</p>' +
      '<p><strong>Urheberrecht:</strong> Musik &amp; Filme nur als <strong>Teilausschnitt</strong> (Musik max. 30s, Filme max. 60s).</p>' +
      '<p id="cp-editor-copyright-warn" class="cp-editor-copyright-warn hidden"></p>' +
      '</div>' +
      '<textarea id="cp-editor-caption" placeholder="Beschreibung… #hashtags" maxlength="500"></textarea>' +
      '</div>' +
      '<input type="file" id="cp-editor-file" accept="video/*,image/*" class="hidden">';
    document.body.appendChild(el);

    HOOKS.forEach((h) => {
      const b = document.createElement('button');
      b.type = 'button';
      b.className = 'cp-hook-chip';
      b.textContent = h;
      b.onclick = () => addOverlay('hook', h);
      $('#cp-hook-list').appendChild(b);
    });

    EMOJIS.forEach((emChar) => {
      const b = document.createElement('button');
      b.type = 'button';
      b.className = 'cp-emoji-btn';
      if (window.VlEmoji) b.innerHTML = VlEmoji.html(emChar, 'cp-emoji-glow', 36);
      else b.textContent = emChar;
      b.onclick = () => addOverlay('emoji', emChar, { y: 55 });
      $('#cp-emoji-grid').appendChild(b);
    });

    Object.keys(FILTERS).forEach((f) => {
      const b = document.createElement('button');
      b.type = 'button';
      b.className = 'cp-filter-btn' + (f === 'none' ? ' active' : '');
      b.textContent = f === 'none' ? 'Normal' : f.charAt(0).toUpperCase() + f.slice(1);
      b.onclick = () => {
        currentFilter = f;
        $$('.cp-filter-btn').forEach((x) => x.classList.remove('active'));
        b.classList.add('active');
        applyFilter();
      };
      $('#cp-filter-grid').appendChild(b);
    });

    $$('.cp-editor-tabs button').forEach((tab) => {
      tab.onclick = () => {
        $$('.cp-editor-tabs button').forEach((t) => t.classList.remove('active'));
        tab.classList.add('active');
        $$('.cp-editor-panel').forEach((p) => p.classList.add('hidden'));
        $('#cp-editor-panel-' + tab.dataset.tool).classList.remove('hidden');
      };
    });

    $('#cp-hook-add').onclick = () => {
      const t = $('#cp-hook-custom').value.trim();
      if (t) addOverlay('hook', t);
    };
    $('#cp-text-add').onclick = () => {
      const t = $('#cp-text-input').value.trim();
      if (t) addOverlay('text', t);
    };
    $('#cp-editor-delete').onclick = removeSelected;
    $('#cp-editor-cancel').onclick = () => {
      close();
      if (onCancel) onCancel();
    };
    document.addEventListener('pointermove', onDragMove);
    document.addEventListener('pointerup', endDrag);
  }

  function $$(s) {
    return document.querySelectorAll(s);
  }

  function updateCopyrightWarn() {
    const warn = $('#cp-editor-copyright-warn');
    if (!warn || !window.VlCopyright) return;
    const caption = ($('#cp-editor-caption') && $('#cp-editor-caption').value.trim()) || '';
    const hashtags = (caption.match(/#\w+/g) || []).map((h) => h.slice(1));
    const niches = (openOpts && openOpts.niches) || [];
    let durationSec = 0;
    if (mediaType === 'video') {
      const v = $('#cp-editor-media');
      durationSec = v && v.duration ? v.duration : 0;
    }
    const cr = VlCopyright.check({
      type: mediaType,
      caption,
      hashtags,
      niches,
      durationSec,
    });
    if (!cr.ok) {
      warn.textContent = cr.reason;
      warn.classList.remove('hidden');
      return;
    }
    const cat = VlCopyright.detectCategory(caption, hashtags, niches);
    if (cat) {
      warn.textContent = VlCopyright.hintFor(cat);
      warn.classList.remove('hidden');
      return;
    }
    warn.textContent = '';
    warn.classList.add('hidden');
  }

  function open(opts = {}) {
    openOpts = opts;
    buildShell();
    overlays = [];
    currentFilter = 'none';
    mediaSrc = '';
    onClose = opts.onPosted || null;
    onCancel = opts.onCancel || null;
    $('#cp-editor-caption').value = '';
    $('#cp-editor-caption').oninput = () => updateCopyrightWarn();
    updateCopyrightWarn();
    $('#cp-editor-stage').innerHTML = '<p class="cp-editor-pick">Video oder Foto wählen</p>';
    show($('#cp-editor-screen'));
    hide($('#main-screen'));
    hide($('#profile-screen'));

    const fileInput = $('#cp-editor-file');
    fileInput.onchange = async (e) => {
      const file = e.target.files[0];
      if (!file) return;
      await loadMedia(file);
      refreshSelect();
    };

    if (opts.file) {
      loadMedia(opts.file).then(() => refreshSelect());
    } else {
      fileInput.click();
    }

    $('#cp-editor-post').onclick = async () => {
      if (!mediaSrc) return;
      const btn = $('#cp-editor-post');
      btn.disabled = true;
      try {
        let dataUrl = mediaSrc;
        let thumb = '';
        let durationSec = 0;
        if (mediaType === 'photo') {
          dataUrl = await bakePhoto();
          thumb = dataUrl;
        } else {
          const v = $('#cp-editor-media');
          durationSec = v && v.duration ? v.duration : 30;
          thumb = await captureVideoThumb();
        }
        const caption = $('#cp-editor-caption').value.trim();
        const hashtags = (caption.match(/#\w+/g) || []).map((h) => h.slice(1));
        if (window.VlCommunity) {
          const cm = VlCommunity.check(caption);
          if (!cm.ok) throw new Error(cm.reason);
        }
        if (window.VlCopyright) {
          const cr = VlCopyright.check({
            type: mediaType,
            caption,
            hashtags,
            niches: (openOpts && openOpts.niches) || [],
            durationSec,
          });
          if (!cr.ok) throw new Error(cr.reason);
        }
        if (opts.onPost) {
          await opts.onPost({
            type: mediaType,
            dataUrl,
            thumbDataUrl: thumb,
            caption,
            hashtags,
            durationSec,
            overlays: { filter: currentFilter, items: overlays },
          });
        }
        close();
        if (onClose) onClose();
      } catch (err) {
        alert(err.message || 'Fehler beim Posten');
      }
      btn.disabled = false;
    };
  }

  function show(el) {
    el.classList.remove('hidden');
  }

  function close() {
    hide($('#cp-editor-screen'));
    mediaSrc = '';
    overlays = [];
  }

  function hide(el) {
    if (el) el.classList.add('hidden');
  }

  function renderOverlaysOnPost(container, overlaysData, videoEl) {
    const data = overlaysData || { filter: 'none', items: [] };
    const items = data.items || [];
    const filter = FILTERS[data.filter] || '';
    const media = container.querySelector('video, img');
    if (media) media.style.filter = filter;

    let layer = container.querySelector('.cp-post-overlays');
    if (!layer) {
      layer = document.createElement('div');
      layer.className = 'cp-post-overlays';
      container.appendChild(layer);
    }
    layer.innerHTML = '';

    function paintVisible(t) {
      layer.innerHTML = '';
      items.forEach((o) => {
        if (videoEl && o.endSec > 0 && (t < o.startSec || t > o.endSec)) return;
        const el = document.createElement('div');
        el.className = 'cp-post-overlay cp-overlay-' + o.kind;
        el.style.left = o.x + '%';
        el.style.top = o.y + '%';
        el.style.transform = 'translate(-50%,-50%) scale(' + o.scale + ') rotate(' + o.rotation + 'deg)';
        if (o.kind === 'emoji' || o.kind === 'sticker') {
          if (window.VlEmoji) {
            el.innerHTML = VlEmoji.html(o.content, 'cp-emoji-glow', Math.round(o.fontSize * 1.3));
          } else {
            el.textContent = o.content;
            el.style.fontSize = (o.fontSize * 1.2) + 'px';
          }
        } else {
          el.innerHTML = '<span style="color:' + esc(o.color) + ';font-size:' + o.fontSize +
            'px;background:' + esc(o.bg) + '">' + esc(o.content) + '</span>';
        }
        layer.appendChild(el);
      });
    }

    paintVisible(0);
    if (videoEl) {
      videoEl.ontimeupdate = () => paintVisible(videoEl.currentTime || 0);
    }
  }

  return { open, close, renderOverlaysOnPost, HOOKS, EMOJIS, FILTERS };
})();

if (typeof window !== 'undefined') window.VibeLoopEditor = VibeLoopEditor;
