/* ============================================================
   EMAGINE BY BUKOLA — Shared Intake Engine + Booking Service
   Two reusable building blocks consumed by Custom Orders:
     · IntakeEngine  — rich brief: text, links, files, voice, consult
     · BookingWidget — slot calculation, calendar, 15-min holds
   ============================================================ */

const fmtNGN = (n) => "₦" + n.toLocaleString("en-NG");
const genRef = () => "EB-" + Math.random().toString(36).slice(2, 8).toUpperCase();

/* ───────────────────────────────────────────────────────────
   BOOKING SERVICE — decoupled scheduling layer
   Generates slots, marks availability, holds a chosen slot.
   onHold(slot) is called when a slot is reserved.
   ─────────────────────────────────────────────────────────── */
const BW_DAYS = 14;            /* horizon */
const BW_TIMES = ["09:30", "11:00", "12:30", "14:00", "15:30", "17:00"];
const BW_MODES = ["Virtual", "Lagos atelier"];

function buildSlots() {
  /* deterministic-ish availability so calendar feels real */
  const today = new Date();
  const days = [];
  for (let i = 1; i <= BW_DAYS; i++) {
    const d = new Date(today);
    d.setDate(today.getDate() + i);
    const dow = d.getDay();
    if (dow === 0) continue; /* closed Sundays */
    const times = BW_TIMES.filter((_, ti) => (i * 7 + ti * 3) % 5 !== 0); /* some taken */
    days.push({ date: d, times });
  }
  return days;
}

function BookingWidget({ onHeld, compact }) {
  const slots = useRef(buildSlots()).current;
  const [mode, setMode] = useState(BW_MODES[0]);
  const [dayIdx, setDayIdx] = useState(0);
  const [time, setTime] = useState(null);
  const [held, setHeld] = useState(null);
  const [secs, setSecs] = useState(0);

  /* hold countdown */
  useEffect(() => {
    if (!held) return;
    setSecs(15 * 60);
    const t = setInterval(() => setSecs((s) => (s > 0 ? s - 1 : 0)), 1000);
    return () => clearInterval(t);
  }, [held]);

  const day = slots[dayIdx];
  const fmtDay = (d) => d.toLocaleDateString("en-GB", { weekday: "short", day: "numeric", month: "short" });
  const mmss = (s) => Math.floor(s / 60) + ":" + String(s % 60).padStart(2, "0");

  const hold = () => {
    const slot = { mode, date: day.date, time };
    setHeld(slot);
    onHeld && onHeld(slot);
  };

  if (held) {
    return (
      <div className="bw-held">
        <div className="bw-held-badge"><Icon name="check" size={20} /></div>
        <div>
          <strong className="bw-held-title">Slot held for you</strong>
          <p className="bw-held-meta">
            {held.mode} · {held.date.toLocaleDateString("en-GB", { weekday: "long", day: "numeric", month: "long" })} at {held.time}
          </p>
          <p className="bw-held-timer">Held for <span>{mmss(secs)}</span> — confirm at checkout to lock it in.</p>
          <button className="bw-release" onClick={() => { setHeld(null); setTime(null); onHeld && onHeld(null); }}>Choose a different time</button>
        </div>
      </div>
    );
  }

  return (
    <div className={"bw" + (compact ? " bw-compact" : "")}>
      <div className="bw-modes">
        {BW_MODES.map((m) => (
          <button key={m} type="button" className={"chip" + (mode === m ? " active" : "")} onClick={() => setMode(m)}>{m}</button>
        ))}
      </div>

      <div className="bw-days">
        {slots.map((s, i) => (
          <button key={i} type="button"
            className={"bw-day" + (dayIdx === i ? " active" : "") + (s.times.length === 0 ? " full" : "")}
            disabled={s.times.length === 0}
            onClick={() => { setDayIdx(i); setTime(null); }}>
            <span className="bw-day-dow">{s.date.toLocaleDateString("en-GB", { weekday: "short" })}</span>
            <span className="bw-day-num">{s.date.getDate()}</span>
            <span className="bw-day-mon">{s.date.toLocaleDateString("en-GB", { month: "short" })}</span>
          </button>
        ))}
      </div>

      <div className="bw-times">
        {day.times.length === 0 ? (
          <p className="bw-none">No slots remaining — try another day.</p>
        ) : (
          BW_TIMES.map((tm) => {
            const open = day.times.includes(tm);
            return (
              <button key={tm} type="button" disabled={!open}
                className={"bw-time" + (time === tm ? " active" : "") + (!open ? " taken" : "")}
                onClick={() => setTime(tm)}>{tm}{!open && <em>booked</em>}</button>
            );
          })
        )}
      </div>

      <button type="button" className="bw-confirm" disabled={!time} onClick={hold}>
        {time ? `Hold ${fmtDay(day.date)} · ${time}` : "Select a time"}
      </button>
      <p className="bw-note">Slots are held for 15 minutes. Calendar syncs to your stylist automatically.</p>
    </div>
  );
}

/* ───────────────────────────────────────────────────────────
   INTAKE ENGINE — shared rich brief
   Props: context (label shown at top), submitLabel, onSubmit(payload)
   ─────────────────────────────────────────────────────────── */
const IE_LIMITS = { image: 20, video: 80, audio: 25 };
const IE_ICON = { image: "🖼", video: "🎬", audio: "🎵" };

function IntakeEngine({ context, submitLabel = "Submit brief", onSubmit }) {
  const [links, setLinks] = useState([""]);
  const [files, setFiles] = useState([]);          /* {id,name,size,type,over} */
  const [consult, setConsult] = useState(false);
  const [heldSlot, setHeldSlot] = useState(null);
  const [catalogueOpen, setCatalogueOpen] = useState(false);
  const [inspoIds, setInspoIds] = useState([]);    /* selected RB.PRODUCTS ids */

  const INSPO_MAX = 3;
  const inspoProducts = inspoIds.map((id) => RB.byId(id)).filter(Boolean);
  const toggleInspo = (id) =>
    setInspoIds((prev) => {
      if (prev.includes(id)) return prev.filter((x) => x !== id);
      if (prev.length >= INSPO_MAX) return prev;
      return [...prev, id];
    });
  const removeInspo = (id) => setInspoIds((prev) => prev.filter((x) => x !== id));

  /* voice recorder */
  const [recState, setRecState] = useState("idle"); /* idle|recording|recorded */
  const [recSecs, setRecSecs] = useState(0);
  const [audioURL, setAudioURL] = useState(null);
  const recRef = useRef(null), chunksRef = useRef([]), timerRef = useRef(null), streamRef = useRef(null);

  const setLink = (i, v) => setLinks((l) => l.map((x, idx) => (idx === i ? v : x)));
  const addLink = () => setLinks((l) => [...l, ""]);
  const rmLink = (i) => setLinks((l) => (l.length > 1 ? l.filter((_, idx) => idx !== i) : l));

  const onPick = (e, type) => {
    const picked = Array.from(e.target.files).map((f) => ({
      id: Math.random().toString(36).slice(2), name: f.name, size: f.size, type,
      over: f.size > IE_LIMITS[type] * 1024 * 1024,
    }));
    setFiles((prev) => [...prev, ...picked]);
    e.target.value = "";
  };
  const rmFile = (id) => setFiles((prev) => prev.filter((f) => f.id !== id));
  const fmtSize = (b) => (b < 1048576 ? (b / 1024).toFixed(0) + " KB" : (b / 1048576).toFixed(1) + " MB");

  /* recorder controls */
  const startRec = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      streamRef.current = stream;
      chunksRef.current = [];
      const mr = new MediaRecorder(stream);
      mr.ondataavailable = (ev) => ev.data.size && chunksRef.current.push(ev.data);
      mr.onstop = () => {
        const blob = new Blob(chunksRef.current, { type: "audio/webm" });
        setAudioURL(URL.createObjectURL(blob));
        setRecState("recorded");
        stream.getTracks().forEach((t) => t.stop());
      };
      mr.start();
      recRef.current = mr;
      setRecState("recording");
      setRecSecs(0);
      timerRef.current = setInterval(() => setRecSecs((s) => s + 1), 1000);
    } catch (e) {
      setRecState("denied");
    }
  };
  const stopRec = () => {
    recRef.current && recRef.current.state !== "inactive" && recRef.current.stop();
    clearInterval(timerRef.current);
  };
  const delRec = () => { setAudioURL(null); setRecState("idle"); setRecSecs(0); };
  useEffect(() => () => { clearInterval(timerRef.current); streamRef.current && streamRef.current.getTracks().forEach((t) => t.stop()); }, []);

  const submit = (e) => {
    e.preventDefault();
    onSubmit && onSubmit({
      ref: genRef(),
      hasVideo: files.some((f) => f.type === "video" && !f.over),
      consult, heldSlot,
      inspiration: inspoProducts.map((p) => p.name),
    });
  };

  return (
    <form className="ie" onSubmit={submit}>
      {context && <div className="ie-context"><span className="mono">Brief for</span> <strong>{context}</strong></div>}

      {/* ─ Project ─ */}
      <div className="ie-section">
        <div className="ie-slabel">01 — Your project</div>
        <div className="form-grid">
          <div className="field"><label>Name</label><input className="input" required placeholder="Your name" /></div>
          <div className="field"><label>Email</label><input className="input" type="email" required placeholder="you@email.com" /></div>
          <div className="field span2"><label>Event type</label><input className="input" placeholder="Bridal · Red Carpet · Prom · Black-tie gala…" /></div>
          <div className="field span2"><label>Describe your vision</label>
            <textarea className="input" rows="5" required placeholder="Silhouette, fabric, colours, cultural elements, the feeling you're after…"></textarea>
          </div>
          <div className="field"><label>Event date</label><input className="input" type="date" /></div>
          <div className="field"><label>Budget guide (optional)</label><input className="input" placeholder="e.g. ₦500,000 – ₦2,000,000" /></div>
        </div>
      </div>

      {/* ─ Inspiration links ─ */}
      <div className="ie-section">
        <div className="ie-slabel">02 — Inspiration</div>
        <div className="ie-links">
          {links.map((v, i) => (
            <div className="ie-link-row" key={i}>
              <input className="input" type="url" value={v} onChange={(e) => setLink(i, e.target.value)} placeholder="https://pin.it/… · instagram.com/…" />
              <button type="button" className="ie-x" onClick={() => rmLink(i)} aria-label="Remove">×</button>
            </div>
          ))}
        </div>
        <button type="button" className="ie-add" onClick={addLink}>+ Add another link</button>

        <button type="button" className="ie-catalogue-btn" onClick={() => setCatalogueOpen(true)}>
          <Icon name="spark" size={15} /> Add from catalogue
        </button>
        <span className="ie-catalogue-hint">
          {inspoIds.length > 0 ? `${inspoIds.length}/${INSPO_MAX} selected` : "Up to 3"}
        </span>

        {inspoProducts.length > 0 && (
          <div className="ie-inspo">
            <div className="ie-inspo-label">Inspiration</div>
            <div className="ie-inspo-chips">
              {inspoProducts.map((p) => (
                <span className="ie-chip" key={p.id}>
                  <Ph label={p.label} ratio="square" className="ie-chip-ph" />
                  <span className="ie-chip-name">{p.name}</span>
                  <button type="button" className="ie-chip-x" onClick={() => removeInspo(p.id)} aria-label={"Remove " + p.name}>×</button>
                </span>
              ))}
            </div>
          </div>
        )}

        {catalogueOpen && (
          <div className="modal-overlay" onClick={() => setCatalogueOpen(false)}>
            <div className="modal-card ie-catalogue-modal" onClick={(e) => e.stopPropagation()}>
              <button className="modal-close" onClick={() => setCatalogueOpen(false)} aria-label="Close">×</button>
              <div className="modal-h">Add from catalogue</div>
              <p className="ie-catalogue-sub">
                Select up to {INSPO_MAX} pieces that capture the look you're after — we'll use them as reference for your commission.
                {" "}<strong>{inspoIds.length >= INSPO_MAX ? `Max ${INSPO_MAX} selected (${inspoIds.length}/${INSPO_MAX})` : `${inspoIds.length}/${INSPO_MAX} selected`}</strong>
              </p>
              <div className="ie-catalogue-grid">
                {RB.PRODUCTS.map((p) => {
                  const on = inspoIds.includes(p.id);
                  const full = !on && inspoIds.length >= INSPO_MAX;
                  return (
                    <button type="button" key={p.id} disabled={full} className={"ie-cat-card" + (on ? " on" : "") + (full ? " full" : "")} onClick={() => toggleInspo(p.id)}>
                      <Ph label={p.label} ratio="portrait" className="ie-cat-ph" />
                      {on && <span className="ie-cat-check"><Icon name="check" size={14} /></span>}
                      <span className="ie-cat-name">{p.name}</span>
                    </button>
                  );
                })}
              </div>
              <button type="button" className="modal-btn" onClick={() => setCatalogueOpen(false)}>
                Done{inspoIds.length > 0 ? ` — ${inspoIds.length} selected` : ""}
              </button>
            </div>
          </div>
        )}
      </div>

      {/* ─ Files ─ */}
      <div className="ie-section">
        <div className="ie-slabel">03 — Reference files</div>
        <div className="ie-zones">
          {["image", "video", "audio"].map((type) => (
            <label className="ie-zone" key={type}>
              <input type="file" accept={type + "/*"} multiple onChange={(e) => onPick(e, type)} />
              <span className="ie-zone-ic">{IE_ICON[type]}</span>
              <span className="ie-zone-l">{type === "image" ? "Images" : type === "video" ? "Video" : "Audio"}</span>
              <span className="ie-zone-lim">Up to {IE_LIMITS[type]} MB each</span>
            </label>
          ))}
        </div>
        {files.length > 0 && (
          <div className="ie-files">
            {files.map((f) => (
              <div className={"ie-file" + (f.over ? " over" : "")} key={f.id}>
                <span className="ie-file-ic">{IE_ICON[f.type]}</span>
                <span className="ie-file-name">{f.name}</span>
                <span className="ie-file-size">{fmtSize(f.size)}</span>
                <button type="button" className="ie-file-x" onClick={() => rmFile(f.id)} aria-label="Remove">×</button>
                {f.over && <span className="ie-file-warn">Exceeds {IE_LIMITS[f.type]} MB limit — won't upload</span>}
              </div>
            ))}
          </div>
        )}
      </div>

      {/* ─ Voice note ─ */}
      <div className="ie-section">
        <div className="ie-slabel">04 — Voice note <em className="ie-opt">optional</em></div>
        <div className="ie-rec">
          <button type="button"
            className={"ie-rec-btn " + (recState === "recording" ? "rec" : "idle")}
            onClick={recState === "recording" ? stopRec : startRec}
            aria-label={recState === "recording" ? "Stop" : "Record"}>
            {recState === "recording" ? "■" : "🎙"}
          </button>
          <div className="ie-rec-meta">
            <div className="ie-rec-timer">{Math.floor(recSecs / 60)}:{String(recSecs % 60).padStart(2, "0")}</div>
            <div className="ie-rec-status">
              {recState === "idle" && "Ready to record"}
              {recState === "recording" && "Recording…"}
              {recState === "recorded" && "Recording saved"}
              {recState === "denied" && "Microphone access denied"}
            </div>
          </div>
          {recState === "recorded" && (
            <div className="ie-rec-actions">
              <audio src={audioURL} controls className="ie-audio" />
              <button type="button" className="ie-rec-act" onClick={() => { delRec(); startRec(); }}>↺ Re-record</button>
              <button type="button" className="ie-rec-act" onClick={delRec}>✕ Delete</button>
            </div>
          )}
        </div>
      </div>

      {/* ─ Consultation ─ */}
      <div className="ie-section">
        <div className="ie-slabel">05 — Consultation</div>
        <button type="button" className={"ie-consult" + (consult ? " on" : "")} onClick={() => setConsult((c) => !c)}>
          <span className="ie-switch"></span>
          <span className="ie-consult-t">
            <strong>Book a consultation call</strong>
            <small>Meet your stylist before we begin — virtual or in person</small>
          </span>
        </button>
        {consult ? (
          <div className="ie-booking">
            <BookingWidget compact onHeld={setHeldSlot} />
          </div>
        ) : (
          <div className="ie-async">
            Our team will review your brief asynchronously and get back to you within <strong>48 hours</strong> with a tailored response.
          </div>
        )}
      </div>

      <div className="ie-submit">
        <Btn type="submit" arrow={false}>{submitLabel}</Btn>
        <p className="ie-fine">Your information is never shared. Files upload securely on submission.</p>
      </div>
    </form>
  );
}

Object.assign(window, { IntakeEngine, BookingWidget, fmtNGN, genRef });
