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

const fmtNGN = (n) => "₦" + n.toLocaleString("en-NG");
const genRef = () => "RB-" + 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", "London showroom"];

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);

  /* 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,
    });
  };

  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>Occasion</label><input className="input" placeholder="Traditional wedding · Owambe · 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. ₦400k–₦600k" /></div>
        </div>
      </div>

      {/* ─ Inspiration links ─ */}
      <div className="ie-section">
        <div className="ie-slabel">02 — Inspiration links</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>
      </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 });
