/* global React, Icon, ImageCropper */
(function(){
const { useState, useEffect, useRef, useCallback } = React;

/* =============================================================
   MediaStep.jsx — step-4 media stage of the upload wizard
   --------------------------------------------------------------
   · image  → multi-slide gallery, live preview, per-slide edit
   · video  → preview + poster picked from a frame (client-side)
              or an uploaded image
   · audio  → preview + square cover image
   All editing runs through <ImageCropper>. A small resumable
   (tus-style) progress bar reflects the background upload.
   ============================================================= */

const fa = (n) => String(n).replace(/\d/g, d => "۰۱۲۳۴۵۶۷۸۹"[d]);
const fmtTime = (s) => {
  if (!isFinite(s) || s < 0) s = 0;
  const m = Math.floor(s / 60), ss = Math.floor(s % 60);
  return fa(m) + ":" + fa(String(ss).padStart(2, "0"));
};
let _uid = 0;
const uid = () => "m" + (++_uid) + "-" + Math.random().toString(36).slice(2, 6);

/* festival-toned placeholder so the flow is explorable without a real file */
const SAMPLE_GRADS = [
  ["#3a1d5e", "#ff4ea8"], ["#0e2740", "#44e3b8"],
  ["#2a1840", "#ff8a3d"], ["#10243a", "#4be3ff"],
];
function sampleImage(i) {
  const w = 1080, h = 1350;
  const c = document.createElement("canvas"); c.width = w; c.height = h;
  const x = c.getContext("2d");
  const g = SAMPLE_GRADS[i % SAMPLE_GRADS.length];
  const lg = x.createLinearGradient(0, 0, w, h);
  lg.addColorStop(0, g[0]); lg.addColorStop(1, g[1]);
  x.fillStyle = lg; x.fillRect(0, 0, w, h);
  x.globalAlpha = 0.16; x.fillStyle = "#fff";
  for (let k = 0; k < 7; k++) {
    x.beginPath();
    x.arc(Math.random() * w, Math.random() * h, 60 + Math.random() * 180, 0, Math.PI * 2);
    x.fill();
  }
  x.globalAlpha = 1;
  x.fillStyle = "rgba(255,255,255,.9)";
  x.font = "600 64px sans-serif"; x.textAlign = "center";
  x.fillText("تصویر نمونه " + fa(i + 1), w / 2, h / 2);
  return c.toDataURL("image/jpeg", 0.9);
}

/* short real sample clip via canvas→MediaRecorder (lets frame-capture work in demo) */
async function sampleVideo() {
  if (!("MediaRecorder" in window)) return null;
  const c = document.createElement("canvas"); c.width = 720; c.height = 1280;
  const x = c.getContext("2d");
  const mime = ["video/webm;codecs=vp9", "video/webm;codecs=vp8", "video/webm"]
    .find(m => { try { return MediaRecorder.isTypeSupported(m); } catch (e) { return false; } });
  if (!mime || !c.captureStream) return null;
  const stream = c.captureStream(25);
  const rec = new MediaRecorder(stream, { mimeType: mime });
  const chunks = [];
  rec.ondataavailable = e => e.data.size && chunks.push(e.data);
  const stopped = new Promise(r => { rec.onstop = r; });
  rec.start();
  await new Promise(res => {
    const t0 = Date.now();
    const iv = setInterval(() => {
      const t = (Date.now() - t0) / 1000;
      const g = x.createLinearGradient(0, 0, 720, 1280);
      g.addColorStop(0, `hsl(${(t * 70) % 360} 78% 56%)`);
      g.addColorStop(1, `hsl(${(t * 70 + 140) % 360} 78% 46%)`);
      x.fillStyle = g; x.fillRect(0, 0, 720, 1280);
      x.fillStyle = "rgba(255,255,255,.92)"; x.textAlign = "center";
      x.font = "600 80px sans-serif";
      x.fillText("نمونه ویدیو", 360, 620);
      x.font = "600 200px sans-serif";
      x.fillText(fa(Math.min(3, Math.floor(t) + 1)), 360, 820);
      if (t >= 3) { clearInterval(iv); try { rec.stop(); } catch (e) {} res(); }
    }, 40);
  });
  await stopped;
  const blob = new Blob(chunks, { type: mime });
  return { url: URL.createObjectURL(blob), name: "نمونه.webm", size: blob.size };
}

async function sampleAudio() {
  if (!("MediaRecorder" in window)) return null;
  const AC = window.AudioContext || window.webkitAudioContext;
  if (!AC) return null;
  const ac = new AC();
  const dest = ac.createMediaStreamDestination();
  const mime = ["audio/webm;codecs=opus", "audio/webm", "audio/ogg"]
    .find(m => { try { return MediaRecorder.isTypeSupported(m); } catch (e) { return false; } });
  if (!mime) { ac.close(); return null; }
  const rec = new MediaRecorder(dest.stream, { mimeType: mime });
  const chunks = [];
  rec.ondataavailable = e => e.data.size && chunks.push(e.data);
  const stopped = new Promise(r => { rec.onstop = r; });
  const o = ac.createOscillator(), g = ac.createGain();
  g.gain.value = 0.06; o.type = "sine"; o.connect(g); g.connect(dest); o.start();
  [330, 392, 440, 392, 494].forEach((f, i) => o.frequency.setValueAtTime(f, ac.currentTime + i * 0.5));
  rec.start();
  await new Promise(r => setTimeout(r, 2600));
  o.stop(); rec.stop(); await stopped; ac.close();
  const blob = new Blob(chunks, { type: mime });
  return { url: URL.createObjectURL(blob), name: "نمونه.webm", size: blob.size };
}

window.MediaStep = function MediaStep({ picked, onBack, onContinue }) {
  const isImg = picked.id === "image";
  const isVideo = picked.id === "video";
  const isAudio = picked.id === "audio";

  const [images, setImages] = useState([]);        // [{id,url,name}]
  const [activeId, setActiveId] = useState(null);
  const [mediaFile, setMediaFile] = useState(null); // {url,name,size}
  const [poster, setPoster] = useState(null);       // {url,from,t}
  const [drag, setDrag] = useState(false);
  const [busy, setBusy] = useState(false);

  // video poster helpers
  const videoRef = useRef(null);
  const [vdur, setVdur] = useState(0);
  const [vtime, setVtime] = useState(0);
  const [strip, setStrip] = useState([]);
  const [stripBusy, setStripBusy] = useState(false);

  // image editor
  const [crop, setCrop] = useState(null);          // {src, onApply, ...cfg}

  const fileRef = useRef(null);
  const posterRef = useRef(null);

  const hasMedia = isImg ? images.length > 0 : !!mediaFile;
  const active = images.find(i => i.id === activeId) || images[0] || null;

  /* ---- resumable upload progress (visual) ---- */
  const [prog, setProg] = useState(0);
  useEffect(() => {
    if (!hasMedia) { setProg(0); return; }
    if (prog >= 100) return;
    let p = prog;
    const id = setInterval(() => {
      p = Math.min(100, p + Math.random() * 8 + 5);
      setProg(p);
      if (p >= 100) clearInterval(id);
    }, 170);
    return () => clearInterval(id);
  // eslint-disable-next-line
  }, [hasMedia]);

  /* ---- IMAGE: add files / samples ---- */
  const addImages = (files) => {
    const arr = Array.from(files || []).filter(f => f.type.startsWith("image/"));
    if (!arr.length) return;
    const items = arr.map(f => ({ id: uid(), url: URL.createObjectURL(f), name: f.name }));
    setImages(prev => {
      const next = [...prev, ...items];
      if (!activeId) setActiveId(items[0].id);
      return next;
    });
  };
  const addSample = () => {
    const it = { id: uid(), url: sampleImage(images.length), name: "نمونه.jpg" };
    setImages(prev => [...prev, it]);
    setActiveId(a => a || it.id);
  };
  const removeImage = (id) => {
    setImages(prev => {
      const next = prev.filter(i => i.id !== id);
      if (activeId === id) setActiveId(next.length ? next[0].id : null);
      return next;
    });
  };
  const replaceImage = (id, url) =>
    setImages(prev => prev.map(i => i.id === id ? { ...i, url } : i));

  // drag-reorder slides (desktop DnD)
  const dragIdx = useRef(null);
  const onThumbDragStart = (i) => { dragIdx.current = i; };
  const onThumbDragOver = (e, i) => {
    e.preventDefault();
    if (dragIdx.current === null || dragIdx.current === i) return;
    setImages(prev => {
      const a = [...prev]; const [m] = a.splice(dragIdx.current, 1); a.splice(i, 0, m);
      dragIdx.current = i; return a;
    });
  };

  const editImage = (img) => setCrop({
    src: img.url, title: "ویرایش اسلاید", shape: "rect", enableFilters: true,
    allowShapeToggle: false,
    aspectOptions: [
      { id: "45", label: "۴:۵", ar: 4/5, icon: "portrait" },
      { id: "1",  label: "۱:۱", ar: 1,   icon: "square" },
      { id: "169",label: "۱۶:۹",ar: 16/9, icon: "rect" },
    ],
    onApply: (url) => { replaceImage(img.id, url); setCrop(null); },
  });

  /* ---- VIDEO / AUDIO: pick file / sample ---- */
  const pickMedia = (f) => {
    if (!f) return;
    const ok = isVideo ? f.type.startsWith("video/") : f.type.startsWith("audio/");
    if (!ok) return;
    setMediaFile({ url: URL.createObjectURL(f), name: f.name, size: f.size });
    setPoster(null); setStrip([]); setVdur(0); setVtime(0);
  };
  const useSampleMedia = async () => {
    setBusy(true);
    try {
      const gen = isVideo ? sampleVideo() : sampleAudio();
      const guard = new Promise(r => setTimeout(() => r(null), 14000));
      const s = await Promise.race([gen, guard]);
      if (s) { setMediaFile(s); setPoster(null); setStrip([]); }
      else alert("ساخت نمونه طول کشید یا پشتیبانی نشد — یه فایل انتخاب کن.");
    } catch (e) {
      alert("ساخت نمونه نشد — یه فایل انتخاب کن.");
    } finally { setBusy(false); }
  };

  /* ---- VIDEO poster: filmstrip + frame capture ---- */
  const buildStrip = useCallback(async (url, duration) => {
    setStripBusy(true);
    try {
      const v = document.createElement("video");
      v.src = url; v.muted = true; v.crossOrigin = "anonymous"; v.preload = "auto";
      await new Promise((res, rej) => { v.onloadeddata = res; v.onerror = rej; });
      const N = 6, out = [];
      const ar = (v.videoWidth / v.videoHeight) || 9/16;
      for (let i = 0; i < N; i++) {
        const t = duration * (i + 0.5) / N;
        await new Promise(res => {
          v.onseeked = res; v.onerror = res;
          v.currentTime = Math.min(t, Math.max(0, duration - 0.05));
        });
        const c = document.createElement("canvas");
        c.height = 132; c.width = Math.round(132 * ar);
        c.getContext("2d").drawImage(v, 0, 0, c.width, c.height);
        out.push({ t, url: c.toDataURL("image/jpeg", 0.7) });
      }
      setStrip(out);
    } catch (e) {
      setStrip([]);
    } finally { setStripBusy(false); }
  }, []);

  const onVideoMeta = () => {
    const v = videoRef.current; if (!v) return;
    setVdur(v.duration || 0);
    if (isVideo && v.duration && isFinite(v.duration)) buildStrip(mediaFile.url, v.duration);
  };
  const captureFrame = () => {
    const v = videoRef.current;
    if (!v || !v.videoWidth) return;
    const c = document.createElement("canvas");
    c.width = v.videoWidth; c.height = v.videoHeight;
    c.getContext("2d").drawImage(v, 0, 0);
    setPoster({ url: c.toDataURL("image/jpeg", 0.9), from: "frame", t: v.currentTime });
  };
  const seekTo = (t) => {
    const v = videoRef.current; if (!v) return;
    v.currentTime = Math.min(t, Math.max(0, (v.duration || 0) - 0.05));
    setVtime(t);
  };

  /* ---- poster / cover via uploaded image (cropped) ---- */
  const editPoster = (url, forAudio) => setCrop({
    src: url,
    title: forAudio ? "کاور صوت" : "پوستر ویدیو",
    shape: "rect", enableFilters: true, allowShapeToggle: false,
    aspectOptions: forAudio
      ? [{ id: "1", label: "۱:۱", ar: 1, icon: "square" }]
      : [{ id: "169", label: "۱۶:۹", ar: 16/9, icon: "rect" }, { id: "45", label: "۴:۵", ar: 4/5, icon: "portrait" }],
    applyLabel: forAudio ? "ثبت کاور" : "ثبت پوستر",
    onApply: (out) => { setPoster({ url: out, from: "upload" }); setCrop(null); },
  });
  const onPosterFile = (f) => {
    if (!f || !f.type.startsWith("image/")) return;
    editPoster(URL.createObjectURL(f), isAudio);
  };

  // ---- header sub copy
  const sub = isImg
    ? "می‌تونی چند تصویر بذاری — به‌صورت اسلاید نشون داده می‌شن. هر کدوم رو جدا ببُر و تنظیم کن."
    : isVideo
      ? "ویدیوت رو ببین، بعد یه فریم رو به‌عنوان پوستر انتخاب کن — یا یه تصویر بذار."
      : "فایل صوتی رو بذار و یه کاور مربعی براش انتخاب کن.";

  return (
    <div className="kd-wizard__step">
      <button className="kd-wizard__back" onClick={onBack}><Icon name="chevron" size={16} stroke={2} /> برگرد</button>
      <h2 className="kd-wizard__h" style={{ color: picked.color }}>
        <Icon name={picked.icon} size={24} stroke={1.7} style={{ verticalAlign: "middle", marginInlineEnd: 8 }} />
        {isImg ? "تصویرها" : isVideo ? "ویدیو و پوستر" : "صوت و کاور"}
      </h2>
      <p className="kd-wizard__sub">{sub}</p>

      {/* ====================== IMAGE ====================== */}
      {isImg && (
        <div className="kd-media">
          {images.length === 0 ? (
            <label className={`kd-wizard__drop kd-media__drop ${drag ? "is-drag" : ""}`}
              onDragOver={e => { e.preventDefault(); setDrag(true); }}
              onDragLeave={() => setDrag(false)}
              onDrop={e => { e.preventDefault(); setDrag(false); addImages(e.dataTransfer.files); }}>
              <div className="kd-wizard__drop-icon"><Icon name="image" size={36} stroke={1.6} /></div>
              <div className="kd-wizard__drop-h">تصویرها رو بکش بیار اینجا</div>
              <div className="kd-wizard__drop-p">یا کلیک کن · چند تا با هم · تا {fa(picked.sizeMB)} مگ</div>
              <input ref={fileRef} type="file" accept="image/*" multiple
                onChange={e => addImages(e.target.files)} />
            </label>
          ) : (
            <React.Fragment>
              <div className="kd-media__stage">
                {active && <img src={active.url} alt="" className="kd-media__preview" />}
                <div className="kd-media__stage-top">
                  <span className="kd-media__count">اسلاید {fa(images.findIndex(i => i.id === active?.id) + 1)} از {fa(images.length)}</span>
                </div>
                <div className="kd-media__stage-actions">
                  <button className="kd-media__round" onClick={() => active && editImage(active)} aria-label="ویرایش">
                    <Icon name="crop" size={18} stroke={1.9} />
                  </button>
                  <button className="kd-media__round kd-media__round--danger" onClick={() => active && removeImage(active.id)} aria-label="حذف">
                    <Icon name="trash" size={18} stroke={1.9} />
                  </button>
                </div>
              </div>

              {/* slide strip */}
              <div className="kd-media__strip">
                {images.map((img, i) => (
                  <button key={img.id}
                    className={`kd-media__thumb ${img.id === active?.id ? "is-active" : ""}`}
                    draggable onDragStart={() => onThumbDragStart(i)}
                    onDragOver={e => onThumbDragOver(e, i)} onDragEnd={() => (dragIdx.current = null)}
                    onClick={() => setActiveId(img.id)}>
                    <img src={img.url} alt="" />
                    <span className="kd-media__thumb-n">{fa(i + 1)}</span>
                    <span className="kd-media__thumb-x" onClick={e => { e.stopPropagation(); removeImage(img.id); }}>
                      <Icon name="close" size={11} stroke={2.4} />
                    </span>
                  </button>
                ))}
                <button className="kd-media__addtile" onClick={() => fileRef.current?.click()} aria-label="افزودن تصویر">
                  <Icon name="plus" size={20} stroke={2} />
                  <span>افزودن</span>
                </button>
                <input ref={fileRef} type="file" accept="image/*" multiple style={{ display: "none" }}
                  onChange={e => addImages(e.target.files)} />
              </div>
              <p className="kd-media__tip"><Icon name="grip" size={12} stroke={2} /> برای تغییر ترتیب، تصویرها رو بکش</p>
            </React.Fragment>
          )}

          <button className="kd-media__sample" onClick={addSample}>
            <Icon name="image" size={13} stroke={2} /> {images.length ? "افزودن تصویر نمونه" : "استفاده از تصویر نمونه"}
          </button>
        </div>
      )}

      {/* ====================== VIDEO ====================== */}
      {isVideo && (
        <div className="kd-media">
          {!mediaFile ? (
            <label className={`kd-wizard__drop kd-media__drop ${drag ? "is-drag" : ""}`}
              onDragOver={e => { e.preventDefault(); setDrag(true); }}
              onDragLeave={() => setDrag(false)}
              onDrop={e => { e.preventDefault(); setDrag(false); pickMedia(e.dataTransfer.files?.[0]); }}>
              <div className="kd-wizard__drop-icon"><Icon name="video" size={36} stroke={1.6} /></div>
              <div className="kd-wizard__drop-h">ویدیوت رو بکش بیار اینجا</div>
              <div className="kd-wizard__drop-p">یا کلیک کن · تا {fa(picked.sizeMB)} مگ</div>
              <input type="file" accept="video/*" onChange={e => pickMedia(e.target.files?.[0])} />
            </label>
          ) : (
            <React.Fragment>
              <div className="kd-media__videowrap">
                <video ref={videoRef} src={mediaFile.url} className="kd-media__video"
                  controls playsInline preload="auto"
                  onLoadedMetadata={onVideoMeta}
                  onTimeUpdate={e => setVtime(e.target.currentTime)} />
              </div>

              {/* poster picker */}
              <div className="kd-media__poster-head">
                <h4><Icon name="image" size={15} stroke={1.9} /> پوستر ویدیو</h4>
                <span className="kd-wizard__tustag"><Icon name="scissors" size={11} stroke={2.2} /> پردازش در مرورگر</span>
              </div>

              <div className="kd-media__scrub">
                <input type="range" min="0" max={vdur || 0} step="0.05" value={Math.min(vtime, vdur || 0)}
                  onChange={e => seekTo(parseFloat(e.target.value))} aria-label="انتخاب لحظه" />
                <span className="kd-media__time">{fmtTime(vtime)} / {fmtTime(vdur)}</span>
              </div>
              <button className="kd-media__capture" onClick={captureFrame} disabled={!vdur}>
                <Icon name="scissors" size={16} stroke={2.1} /> همین فریم رو پوستر کن
              </button>

              {/* filmstrip of candidate frames */}
              {(stripBusy || strip.length > 0) && (
                <div className="kd-media__filmstrip">
                  {stripBusy && Array.from({ length: 6 }).map((_, i) => (
                    <span key={i} className="kd-media__frame is-loading" />
                  ))}
                  {strip.map((f, i) => (
                    <button key={i} className={`kd-media__frame ${poster?.t === f.t ? "is-on" : ""}`}
                      onClick={() => { seekTo(f.t); setPoster({ url: f.url, from: "frame", t: f.t }); }}>
                      <img src={f.url} alt="" />
                      <span>{fmtTime(f.t)}</span>
                    </button>
                  ))}
                </div>
              )}

              <div className="kd-media__poster-row">
                <div className={`kd-media__poster-prev ${poster ? "is-set" : ""}`}>
                  {poster ? <img src={poster.url} alt="" /> : <Icon name="image" size={22} stroke={1.6} />}
                  {poster && <span className="kd-media__poster-tag">{poster.from === "frame" ? "از فریم" : "تصویر"}</span>}
                </div>
                <div className="kd-media__poster-cta">
                  <p>{poster ? "پوستر انتخاب شد." : "هنوز پوستری انتخاب نشده."}</p>
                  <button onClick={() => posterRef.current?.click()}><Icon name="upload" size={13} stroke={2.1} /> آپلود تصویر پوستر</button>
                  <input ref={posterRef} type="file" accept="image/*" style={{ display: "none" }}
                    onChange={e => onPosterFile(e.target.files?.[0])} />
                </div>
              </div>
            </React.Fragment>
          )}

          {!mediaFile && (
            <button className="kd-media__sample" onClick={useSampleMedia} disabled={busy}>
              <Icon name="play" size={13} stroke={2} /> {busy ? "در حال ساخت…" : "استفاده از ویدیوی نمونه"}
            </button>
          )}
        </div>
      )}

      {/* ====================== AUDIO ====================== */}
      {isAudio && (
        <div className="kd-media">
          {!mediaFile ? (
            <label className={`kd-wizard__drop kd-media__drop ${drag ? "is-drag" : ""}`}
              onDragOver={e => { e.preventDefault(); setDrag(true); }}
              onDragLeave={() => setDrag(false)}
              onDrop={e => { e.preventDefault(); setDrag(false); pickMedia(e.dataTransfer.files?.[0]); }}>
              <div className="kd-wizard__drop-icon"><Icon name="audio" size={36} stroke={1.6} /></div>
              <div className="kd-wizard__drop-h">فایل صوتی رو بکش بیار اینجا</div>
              <div className="kd-wizard__drop-p">یا کلیک کن · تا {fa(picked.sizeMB)} مگ</div>
              <input type="file" accept="audio/*" onChange={e => pickMedia(e.target.files?.[0])} />
            </label>
          ) : (
            <React.Fragment>
              <div className="kd-media__audiocard">
                <div className={`kd-media__cover ${poster ? "is-set" : ""}`}>
                  {poster ? <img src={poster.url} alt="" /> : <Icon name="audio" size={30} stroke={1.5} />}
                </div>
                <div className="kd-media__audiobody">
                  <p className="kd-media__audioname">{mediaFile.name}</p>
                  <div className="kd-media__bars">
                    {Array.from({ length: 28 }).map((_, i) => (
                      <span key={i} style={{ height: (20 + Math.abs(Math.sin(i * 1.3)) * 70) + "%" }} />
                    ))}
                  </div>
                  <audio src={mediaFile.url} controls className="kd-media__audio" />
                </div>
              </div>

              <div className="kd-media__poster-head">
                <h4><Icon name="image" size={15} stroke={1.9} /> کاور صوت</h4>
                <span className="kd-wizard__tustag"><Icon name="square" size={11} stroke={2.2} /> مربعی ۱:۱</span>
              </div>
              <div className="kd-media__poster-row">
                <div className={`kd-media__poster-prev kd-media__poster-prev--sq ${poster ? "is-set" : ""}`}>
                  {poster ? <img src={poster.url} alt="" /> : <Icon name="image" size={22} stroke={1.6} />}
                </div>
                <div className="kd-media__poster-cta">
                  <p>{poster ? "کاور انتخاب شد." : "یه تصویر مربعی برای کاور بذار."}</p>
                  <button onClick={() => posterRef.current?.click()}><Icon name="upload" size={13} stroke={2.1} /> {poster ? "تغییر کاور" : "آپلود کاور"}</button>
                  <input ref={posterRef} type="file" accept="image/*" style={{ display: "none" }}
                    onChange={e => onPosterFile(e.target.files?.[0])} />
                </div>
              </div>
            </React.Fragment>
          )}
        </div>
      )}

      {/* ---- resumable upload status ---- */}
      {hasMedia && (
        <div className="kd-media__upload">
          <div className="kd-media__upload-top">
            <span className={`kd-wizard__upload-status ${prog >= 100 ? "is-active" : "is-resume"}`}>
              <span style={{ width: 6, height: 6, borderRadius: "50%", background: "currentColor", boxShadow: "0 0 8px currentColor", display: "inline-block" }} />
              {prog >= 100 ? "آپلود کامل شد" : "در حال آپلود…"}
            </span>
            <span className="kd-wizard__tustag"><Icon name="upload" size={11} stroke={2.2} /> tus · resumable</span>
          </div>
          <div className="kd-wizard__upload-bar"><i style={{ width: prog + "%" }} /></div>
        </div>
      )}

      <button className="kd-btn kd-btn--primary kd-btn--lg" disabled={!hasMedia} onClick={onContinue}>
        ادامه <Icon name="back" size={16} stroke={2.4} />
      </button>

      {/* ---- editor overlay ---- */}
      <ImageCropper open={!!crop} {...(crop || {})} onCancel={() => setCrop(null)} />
    </div>
  );
};
})();
