/* global React */
const { useState, useRef, useEffect } = React;

// Try-it-yourself uploader. Posts to /api/enhance-preview, polls preview-status,
// then fetches the enhanced bytes and applies a watermark client-side. Falls back
// to a simulated canvas filter if the backend isn't reachable.
function Uploader({ endpoint = "/api/enhance-preview", onBatchAttempt }) {
  const [file, setFile] = useState(null);
  const [previewUrl, setPreviewUrl] = useState(null);
  const [resultUrl, setResultUrl] = useState(null);
  const [status, setStatus] = useState("idle"); // idle | uploading | processing | done | error
  const [errMsg, setErrMsg] = useState("");
  const [drag, setDrag] = useState(false);
  const inputRef = useRef(null);
  const turnstileRef = useRef(null);
  const pendingTokenRef = useRef(null);

  // Render an invisible Turnstile widget once the script has loaded.
  useEffect(() => {
    let cancelled = false;
    let timer;
    const tryRender = () => {
      if (cancelled) return;
      const tApi = window.turnstile;
      const cfg = window.PIXFIXCO_CONFIG;
      if (!tApi || !cfg || !cfg.turnstileSiteKey) {
        timer = setTimeout(tryRender, 250);
        return;
      }
      turnstileRef.current = tApi.render("#pfx-turnstile", {
        sitekey: cfg.turnstileSiteKey,
        size: "invisible",
        callback: (token) => {
          if (pendingTokenRef.current) {
            pendingTokenRef.current(token);
            pendingTokenRef.current = null;
          }
        },
        "error-callback": () => {
          if (pendingTokenRef.current) {
            pendingTokenRef.current("");
            pendingTokenRef.current = null;
          }
        },
      });
    };
    tryRender();
    return () => {
      cancelled = true;
      clearTimeout(timer);
      if (turnstileRef.current && window.turnstile) {
        try { window.turnstile.remove(turnstileRef.current); } catch (_) {}
      }
    };
  }, []);

  const getTurnstileToken = () => new Promise((resolve) => {
    if (!turnstileRef.current || !window.turnstile) return resolve("");
    pendingTokenRef.current = resolve;
    try { window.turnstile.reset(turnstileRef.current); } catch (_) {}
    try { window.turnstile.execute(turnstileRef.current); } catch (_) { resolve(""); }
  });

  const accept = (f) => {
    if (!f) return;
    if (!f.type.startsWith("image/")) {
      setErrMsg("That's not an image. Try a JPG or PNG.");
      setStatus("error");
      return;
    }
    if (f.size > 25 * 1024 * 1024) {
      setErrMsg("That photo is over 25 MB. Try a smaller one.");
      setStatus("error");
      return;
    }
    setFile(f);
    setResultUrl(null);
    setErrMsg("");
    const url = URL.createObjectURL(f);
    setPreviewUrl(url);
    setStatus("idle");
  };

  const onPick = (e) => accept(e.target.files?.[0]);
  const onDrop = (e) => {
    e.preventDefault();
    setDrag(false);
    accept(e.dataTransfer.files?.[0]);
  };

  const pollPreview = async (previewId) => {
    const start = Date.now();
    const timeoutMs = 90 * 1000;
    while (Date.now() - start < timeoutMs) {
      await new Promise((r) => setTimeout(r, 2000));
      const res = await fetch(`/api/preview-status?id=${encodeURIComponent(previewId)}`);
      if (!res.ok) throw new Error(`status ${res.status}`);
      const body = await res.json();
      if (body.status === "done") return body.url;
      if (body.status === "failed") throw new Error(body.message || "enhancement failed");
    }
    throw new Error("timed out waiting for enhancement");
  };

  const enhance = async () => {
    if (!file) return;
    setErrMsg("");
    setStatus("uploading");
    try {
      const token = await getTurnstileToken();
      const fd = new FormData();
      fd.append("image", file);
      fd.append("cf-turnstile-response", token);
      const res = await fetch(endpoint, { method: "POST", body: fd });
      if (!res.ok) {
        const body = await res.json().catch(() => ({}));
        throw new Error(body.error || `HTTP ${res.status}`);
      }
      const { previewId } = await res.json();
      setStatus("processing");

      const imageUrl = await pollPreview(previewId);
      const watermarked = await window.applyDemoWatermark(imageUrl, { applyFakeFilters: false });
      setResultUrl(watermarked);
      setStatus("done");
    } catch (err) {
      // Backend not reachable / not yet configured → keep the demo demoable.
      // For real errors after a successful POST we already showed the spinner.
      console.warn("[uploader] real path failed, falling back to simulate:", err);
      try {
        await simulateEnhance();
      } catch (e2) {
        setErrMsg(String(err.message || err));
        setStatus("error");
      }
    }
  };

  // Fallback: apply CSS filters + watermark via the shared helper so the flow is
  // visible when the backend isn't live (local dev, demo without keys).
  const simulateEnhance = async () => {
    setStatus("processing");
    await new Promise((r) => setTimeout(r, 1400));
    const dataUrl = await window.applyDemoWatermark(previewUrl, { applyFakeFilters: true });
    setResultUrl(dataUrl);
    setStatus("done");
  };

  const reset = () => {
    setFile(null);
    setPreviewUrl(null);
    setResultUrl(null);
    setStatus("idle");
    setErrMsg("");
  };

  return (
    <div className="up-card">
      {/* Hidden Turnstile widget container */}
      <div id="pfx-turnstile" style={{ display: "none" }} />

      <div className="up-head">
        <div>
          <div className="eyebrow">Try it · free</div>
          <h3 className="up-title">Upload one photo. See the difference.</h3>
          <p className="up-sub">We'll return a watermarked preview. Got a whole listing to fix? <a className="link-inline" href="/order">Batch upload →</a></p>
        </div>
      </div>

      {!file && (
        <label
          className={`up-drop ${drag ? "is-drag" : ""}`}
          onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
          onDragLeave={() => setDrag(false)}
          onDrop={onDrop}
        >
          <input ref={inputRef} type="file" accept="image/*" hidden onChange={onPick} />
          <div className="up-drop-inner">
            <div className="up-icon" aria-hidden="true">
              <svg width="34" height="34" viewBox="0 0 24 24" fill="none">
                <path d="M12 16V4M12 4L7 9M12 4L17 9" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
                <path d="M4 16V18C4 19.1046 4.89543 20 6 20H18C19.1046 20 20 19.1046 20 18V16" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
              </svg>
            </div>
            <div className="up-drop-title">Drop a photo here</div>
            <div className="up-drop-sub">or <span className="link-inline">browse</span> — JPG or PNG, up to 25 MB</div>
            <div className="up-chips">
              <span className="chip">✓ No account needed</span>
              <span className="chip">✓ Watermarked preview</span>
              <span className="chip">✓ ~22 sec</span>
            </div>
          </div>
        </label>
      )}

      {file && (
        <div className="up-stage">
          <div className="up-stage-grid">
            <figure className="up-fig">
              <figcaption>Your photo</figcaption>
              <div className="up-img-wrap">
                <img src={previewUrl} alt="Your upload" />
              </div>
            </figure>
            <figure className="up-fig">
              <figcaption>PixFixCo result {resultUrl && <span className="wm-tag">· watermarked</span>}</figcaption>
              <div className="up-img-wrap up-img-wrap-after">
                {resultUrl ? (
                  <img src={resultUrl} alt="Enhanced result" />
                ) : (
                  <div className={`up-placeholder ${status !== "idle" ? "is-working" : ""}`}>
                    {status === "uploading" && <><Spinner/> Submitting…</>}
                    {status === "processing" && <><Spinner/> Enhancing · ~22 sec</>}
                    {status === "idle" && <span className="muted">Click "Enhance" to run</span>}
                  </div>
                )}
              </div>
            </figure>
          </div>

          {errMsg && <div className="up-err">{errMsg}</div>}

          <div className="up-actions">
            <button className="btn btn-ghost" onClick={reset}>Start over</button>
            {status !== "done" ? (
              <button className="btn btn-primary" onClick={enhance} disabled={status === "uploading" || status === "processing"}>
                {status === "uploading" || status === "processing" ? "Working…" : "Enhance photo"}
              </button>
            ) : (
              <>
                <a className="btn btn-ghost" href={resultUrl} download="pixfixco-preview.jpg">Download preview</a>
                <a className="btn btn-primary" href="/order">Fix the whole listing →</a>
              </>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

function Spinner() {
  return (
    <span className="spinner" aria-hidden="true">
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
        <circle cx="12" cy="12" r="9" stroke="currentColor" strokeOpacity="0.25" strokeWidth="2"/>
        <path d="M21 12a9 9 0 0 0-9-9" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
      </svg>
    </span>
  );
}

window.Uploader = Uploader;
