// Post-anything modal — "craigslist of roofers".
// Loads AFTER open-marketplace-signedin.jsx and OVERRIDES window.RLS.PostListingModal.
// Photo sources: drag-drop/upload, AI generation (prototype: styled pool match), library.

const { useState, useRef } = React;


// ── Post types ───────────────────────────────────────────────────────────
const PL_TYPES = [
  { id: "sell",   label: "Sell materials",     photo: "m1" },
  { id: "rent",   label: "Rent out machinery", photo: "q1" },
  { id: "wanted", label: "Wanted",             photo: "m3" },
  { id: "crew",   label: "Offer your crew",    photo: "hero" },
  { id: "work",   label: "Looking for work",   photo: "q2" },
  { id: "job",    label: "Hiring",             photo: "q6" },
];
const PL_BOARD = { wanted: "Wanted", crew: "Crew for hire", work: "For hire", job: "Job opening" };

function PLIcon({ d, size = 22 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <path d={d} />
    </svg>
  );
}

if (!document.getElementById("pl-styles")) {
  const s = document.createElement("style");
  s.id = "pl-styles";
  s.textContent = `
    .pl-card { position: relative; border: none; border-radius: 14px; overflow: hidden; cursor: pointer;
      aspect-ratio: 16 / 10; padding: 0; text-align: left; background: var(--bg-card-soft);
      transition: transform .18s, box-shadow .18s; }
    .pl-card:hover { transform: translateY(-3px) scale(1.015); box-shadow: 0 12px 28px rgba(40,30,10,.2); }
    .pl-card:active { transform: scale(.97); }
    .pl-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
      transition: transform .6s cubic-bezier(.2,.7,.3,1); }
    .pl-card:hover img { transform: scale(1.08); }
    .pl-card .scrim { position: absolute; inset: 0;
      background: linear-gradient(180deg, rgba(27,24,20,0) 30%, rgba(27,24,20,0.78)); }
    .pl-card .lbl { position: absolute; left: 12px; right: 12px; bottom: 10px; color: #FBF7EB;
      font-family: var(--sans); font-size: 15.5px; font-weight: 600;
      text-shadow: 0 1px 8px rgba(27,24,20,.6); }
    .pl-card .go { position: absolute; right: 10px; bottom: 10px; width: 26px; height: 26px; border-radius: 50%;
      background: var(--gold); color: #1B1814; display: grid; place-items: center; font-size: 14px; font-weight: 700;
      opacity: 0; transform: translateX(-6px); transition: opacity .18s, transform .18s; }
    .pl-card:hover .go { opacity: 1; transform: none; }
    @media (prefers-reduced-motion: no-preference) {
      .pl-pop { animation: plPop .45s cubic-bezier(.28,1.3,.45,1) both; }
    }
    @keyframes plPop { from { opacity: 0; transform: translateY(16px) scale(.94); } to { opacity: 1; transform: none; } }
  `;
  document.head.appendChild(s);
}

// ── Photo helpers ────────────────────────────────────────────────────────
function plCompress(file) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    const url = URL.createObjectURL(file);
    img.onload = () => {
      const scale = Math.min(1, 900 / Math.max(img.width, img.height));
      const c = document.createElement("canvas");
      c.width = Math.round(img.width * scale);
      c.height = Math.round(img.height * scale);
      c.getContext("2d").drawImage(img, 0, 0, c.width, c.height);
      URL.revokeObjectURL(url);
      resolve(c.toDataURL("image/jpeg", 0.78));
    };
    img.onerror = reject;
    img.src = url;
  });
}

const PL_AI_MAP = [
  [/shingle|charcoal|architec|gaf|timberline/i, "m1"],
  [/driftwood|owens|duration/i, "m2"],
  [/underlay|felt|roll|synthetic/i, "m3"],
  [/flashing|drip|edge|trim/i, "m5"],
  [/pallet|bundle|surplus/i, "m1"],
  [/lift|equipter|debris/i, "q1"],
  [/hoist|ladder/i, "q2"],
  [/trailer|dump|haul/i, "q4"],
  [/crane|telehandler|boom/i, "q6"],
];
function plAiPick(prompt, kindHint) {
  for (const [re, key] of PL_AI_MAP) if (re.test(prompt)) return key;
  return kindHint === "rent" ? "q1" : "m1";
}

// photos: [{ src, source: 'upload'|'ai'|'lib' }]
function PhotoPicker({ photos, setPhotos, kindHint, title }) {
  const [mode, setMode] = useState("upload");
  const [prompt, setPrompt] = useState("");
  const [genBusy, setGenBusy] = useState(false);
  const [drag, setDrag] = useState(false);
  const fileRef = useRef(null);
  const full = photos.length >= 4;

  const addFiles = async files => {
    const imgs = [...files].filter(f => f.type.startsWith("image/")).slice(0, 4 - photos.length);
    const added = [];
    for (const f of imgs) {
      try { added.push({ src: await plCompress(f), source: "upload" }); } catch (e) {}
    }
    if (added.length) setPhotos(p => [...p, ...added].slice(0, 4));
  };

  const generate = () => {
    if (genBusy || full) return;
    setGenBusy(true);
    const p = (prompt || title || "roofing materials on a pallet").trim();
    setTimeout(() => {
      const key = plAiPick(p, kindHint);
      setPhotos(ph => [...ph, { src: window.MP_PHOTOS[key], source: "ai" }].slice(0, 4));
      setGenBusy(false);
    }, 1800);
  };

  const LIB = kindHint === "rent" ? ["q1", "q2", "q4", "q6"] : ["m1", "m2", "m3", "m5"];

  return (
    <div className="field">
      <span className="field-label">Photos <span style={{ color: "var(--text-3)", fontWeight: 400 }}>· up to 4, first is the cover</span></span>

      {photos.length > 0 && (
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 4 }}>
          {photos.map((ph, i) => (
            <div key={i} style={{ position: "relative", width: 84, height: 60, borderRadius: 8, overflow: "hidden", border: i === 0 ? "2px solid var(--gold-dark)" : "1px solid var(--border)" }}>
              <img src={ph.src} alt="" style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }} />
              {ph.source === "ai" && <span style={{ position: "absolute", left: 4, bottom: 4, fontSize: 9, fontWeight: 700, background: "var(--gold)", color: "#1B1814", padding: "1px 5px", borderRadius: 4 }}>AI</span>}
              <button aria-label="Remove photo" onClick={() => setPhotos(p => p.filter((_, j) => j !== i))}
                      style={{ position: "absolute", top: 3, right: 3, width: 18, height: 18, borderRadius: "50%", border: "none", cursor: "pointer", background: "rgba(27,24,20,0.75)", color: "#fff", fontSize: 11, lineHeight: 1, display: "grid", placeItems: "center", padding: 0 }}>✕</button>
            </div>
          ))}
        </div>
      )}

      <div className="mpx-roleseg" style={{ alignSelf: "flex-start", marginBottom: 8 }}>
        <button className={mode === "upload" ? "active" : ""} onClick={() => setMode("upload")}>Upload</button>
        <button className={mode === "ai" ? "active" : ""} onClick={() => setMode("ai")}>✦ Generate with AI</button>
        <button className={mode === "lib" ? "active" : ""} onClick={() => setMode("lib")}>Library</button>
      </div>

      {mode === "upload" && (
        <div onClick={() => !full && fileRef.current && fileRef.current.click()}
             onDragOver={e => { e.preventDefault(); setDrag(true); }}
             onDragLeave={() => setDrag(false)}
             onDrop={e => { e.preventDefault(); setDrag(false); addFiles(e.dataTransfer.files); }}
             style={{
               border: "2px dashed " + (drag ? "var(--gold-dark)" : "var(--border-strong)"),
               background: drag ? "var(--gold-bg)" : "var(--bg-card-soft)",
               borderRadius: 12, padding: "22px 16px", textAlign: "center",
               cursor: full ? "not-allowed" : "pointer", opacity: full ? 0.5 : 1,
               transition: "background .15s, border-color .15s",
             }}>
          <div style={{ fontSize: 15, fontWeight: 600 }}>{drag ? "Drop them here" : "Drag & drop photos"}</div>
          <div style={{ fontSize: 12.5, color: "var(--text-3)", marginTop: 3 }}>{full ? "4 photos max" : "or tap to browse your phone"}</div>
          <input ref={fileRef} type="file" accept="image/*" multiple style={{ display: "none" }}
                 onChange={e => { addFiles(e.target.files); e.target.value = ""; }} />
        </div>
      )}

      {mode === "ai" && (
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          <div style={{ display: "flex", gap: 8 }}>
            <input className="input" placeholder={"e.g. " + (title || "pallet of charcoal shingles in a supply yard")}
                   value={prompt} onChange={e => setPrompt(e.target.value)}
                   onKeyDown={e => { if (e.key === "Enter") generate(); }} />
            <button className="btn gold" style={{ flexShrink: 0 }} disabled={genBusy || full} onClick={generate}>
              {genBusy ? "Generating…" : "✦ Generate"}
            </button>
          </div>
          {genBusy && (
            <div style={{ position: "relative", width: 130, height: 92, borderRadius: 10, overflow: "hidden", border: "1px solid var(--border)" }}>
              <div className="mpx-shimmer"></div>
              <span style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", fontSize: 11.5, color: "var(--text-3)", fontWeight: 600 }}>✦ dreaming…</span>
            </div>
          )}
          <div style={{ fontSize: 11.5, color: "var(--text-3)" }}>Describe the item — AI shoots it marketplace-style so it looks real to buyers.</div>
        </div>
      )}

      {mode === "lib" && (
        <div className="rls-photo-pick">
          {LIB.map(k => (
            <button key={k} disabled={full} onClick={() => setPhotos(p => [...p, { src: window.MP_PHOTOS[k], source: "lib" }].slice(0, 4))} aria-label="Add library photo">
              <img src={window.MP_PHOTOS[k]} alt="" loading="lazy" />
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

// ── The modal ────────────────────────────────────────────────────────────
function PostAnythingModal({ onClose, onPublished }) {
  const [type, setType] = useState(null);
  const [title, setTitle] = useState("");
  const [detail, setDetail] = useState("");
  const [price, setPrice] = useState("");
  const [cat, setCat] = useState("Shingles");
  const [photos, setPhotos] = useState([]);
  const [done, setDone] = useState(false);
  const [descBusy, setDescBusy] = useState(false);
  const descSeed = useRef("");

  // ✦ AI writes the description from title + price + category
  const plFallbackDesc = () => {
    const bits = [];
    if (type === "sell") bits.push(cat + " in good condition", "priced to move at $" + (price || "—") + "/bundle", "pickup in Mesa — first come, first served");
    else if (type === "rent") bits.push(cat.replace(/s$/, "") + " rental", "$" + (price || "—") + "/day", "well maintained, ready to work — pickup in Mesa");
    else if (type === "wanted") bits.push("Looking for this near Mesa", price ? "budget around $" + price : "open on price", "can pick up right away");
    else if (type === "crew") bits.push("Experienced crew, insured", "$" + (price || "—") + "/day per man", "available now — references on request");
    else if (type === "work") bits.push("Reliable and ready to start", price ? "$" + price + "/hr" : "rate negotiable", "references available");
    else bits.push("Now hiring", price ? "$" + price + "/hr" : "competitive pay", "apply by replying to this post");
    return bits.join(" · ").replace(/^./, c => c.toUpperCase());
  };

  const writeDesc = async () => {
    if (!title.trim() || descBusy) return;
    setDescBusy(true);
    let text = "";
    try {
      if (window.claude && window.claude.complete) {
        const resp = await window.claude.complete(
          "Write a 1-2 sentence marketplace listing description a roofing contractor would post. Plain, confident, no hashtags, no emoji, under 30 words. Respond with ONLY the description text.\n" +
          "Post type: " + type + "\nTitle: " + title + (isMarket ? "\nCategory: " + cat : "") + (price ? "\nPrice: $" + price + unit : "") + "\nLocation: Mesa, AZ"
        );
        text = (resp || "").trim().replace(/^["']|["']$/g, "");
      }
    } catch (e) {}
    if (!text) text = plFallbackDesc();
    descSeed.current = text;
    setDetail(text);
    setDescBusy(false);
  };

  const maybeWriteDesc = () => {
    if (title.trim() && (!detail.trim() || detail === descSeed.current)) writeDesc();
  };

  const isMarket = type === "sell" || type === "rent";
  const kindHint = type === "rent" ? "rent" : "sell";
  const cats = type === "rent" ? window.MP_MACHINERY_CATS.filter(c => c !== "All")
             : window.MP_MATERIAL_CATS.filter(c => c !== "All");
  const unit = type === "rent" ? "/day" : type === "crew" ? "/day per man" : type === "work" || type === "job" ? "/hr" : "";
  const priceLabel = { sell: "Price (/bundle)", rent: "Price (/day)", wanted: "Budget (optional)", crew: "Rate ($/day per man)", work: "Rate ($/hr)", job: "Pay ($/hr)" }[type];
  const titlePh = {
    sell: "e.g. Architectural shingles — Charcoal", rent: "e.g. Ladder hoist — 28 ft",
    wanted: "e.g. Need 30 bundles of Driftwood shingles", crew: "e.g. 4-man tear-off crew available",
    work: "e.g. Foreman, 8 yrs experience — open to work", job: "e.g. Hiring: roofing estimator, full-time",
  }[type];
  const detailPh = {
    sell: "42 bundles · GAF Timberline HDZ", rent: "400 lb capacity · gas",
    wanted: "Color, brand, quantity, when you need it…", crew: "Specialties, insurance, availability…",
    work: "Experience, certifications, when you can start…", job: "Requirements, schedule, benefits…",
  }[type];
  const canPost = title.trim() && (type === "wanted" || type === "work" ? true : isMarket ? parseFloat(price) > 0 : true);

  const publish = () => {
    const id = "u" + Date.now();
    const item = {
      id, title: title.trim(), detail: detail.trim() || "Posted just now",
      price: Math.round(parseFloat(price)) || 0, unit,
      loc: "Mesa, AZ", dist: 0, seller: "you", sold: false, at: Date.now(),
      thumb: "shingle-charcoal",
    };
    if (isMarket) {
      item.kind = type === "sell" ? "materials" : "machinery";
      item.cond = type === "sell" ? "Surplus" : "Rental";
      item.cat = cats.includes(cat) ? cat : cats[0];
      item.unit = type === "sell" ? "/bundle" : "/day";
    } else {
      item.kind = "board";
      item.postType = type;
      item.chip = PL_BOARD[type];
    }
    if (photos[0]) {
      window.MP_PHOTOS[id] = photos[0].src;
      if (photos[0].src.startsWith("data:")) item.img = photos[0].src;
      else item.photoOf = Object.keys(window.MP_PHOTOS).find(k => window.MP_PHOTOS[k] === photos[0].src && k !== id);
      if (photos.length > 1) item.extraImgs = photos.slice(1, 4).map(p => p.src.startsWith("data:") ? p.src : null).filter(Boolean);
    }
    try { window.RLS.saveMyListings([item, ...window.RLS.myListings()]); } catch (e) {}
    setDone(true);
  };

  const doneCopy = {
    sell: "Your listing is live with a JUST LISTED badge.", rent: "Your rental is live with a JUST LISTED badge.",
    wanted: "Your request is on the board — sellers nearby will see it.", crew: "Your crew is on the board — GCs and roofers can reply.",
    work: "You're on the board — companies hiring can reach out.", job: "Your opening is on the board — applicants can reply.",
  }[type];

  return (
    <div className="modal-overlay mpx-overlay-in" onClick={onClose}>
      <div className="modal mpx-modal-in" style={{ maxWidth: 500, maxHeight: "92vh", overflowY: "auto" }} onClick={e => e.stopPropagation()}>
        {done ? (
          <div style={{ padding: "34px 30px 28px", textAlign: "center" }}>
            <div className="rls-check">
              <svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="var(--green)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
            </div>
            <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 24 }}>You're live!</div>
            <div style={{ fontSize: 14, color: "var(--text-2)", marginTop: 8 }}>{doneCopy}</div>
            <button className="btn gold" style={{ marginTop: 20 }}
                    onClick={() => { onPublished(isMarket ? (type === "sell" ? "materials" : "machinery") : "board"); onClose(); }}>
              See it →
            </button>
          </div>
        ) : !type ? (
          <div style={{ padding: "24px 26px 24px" }}>
            <div style={{ display: "flex", justifyContent: "space-between", gap: 12, alignItems: "baseline" }}>
              <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 26 }}>What are you posting?</div>
              <button className="btn ghost sm" onClick={onClose} aria-label="Close">✕</button>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, marginTop: 16 }}>
              {PL_TYPES.map((t, i) => (
                <button key={t.id} onClick={() => setType(t.id)} className="pl-card pl-pop" style={{ animationDelay: (i * 60) + "ms" }}>
                  <img src={t.photo === "hero" ? window.MP_HERO : window.MP_PHOTOS[t.photo]} alt="" loading="lazy" />
                  <span className="scrim"></span>
                  <span className="lbl">{t.label}</span>
                  <span className="go">→</span>
                </button>
              ))}
            </div>
          </div>
        ) : (
          <div style={{ padding: "24px 26px 22px" }}>
            <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
              <button className="btn ghost sm" onClick={() => setType(null)} aria-label="Back">←</button>
              <div style={{ fontFamily: "var(--serif)", fontStyle: "italic", fontSize: 22, flex: 1 }}>{PL_TYPES.find(t => t.id === type).label}</div>
              <button className="btn ghost sm" onClick={onClose} aria-label="Close">✕</button>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 12, marginTop: 14 }}>
              <div className="field">
                <span className="field-label">Title</span>
                <input className="input" placeholder={titlePh} value={title} onChange={e => setTitle(e.target.value)} onBlur={maybeWriteDesc} autoFocus />
              </div>
              <div style={{ display: "grid", gridTemplateColumns: isMarket ? "1fr 1fr" : "1fr", gap: 10 }}>
                <div className="field">
                  <span className="field-label">{priceLabel}</span>
                  <input className="input" type="number" min="0" placeholder={type === "wanted" ? "—" : "28"} value={price} onChange={e => setPrice(e.target.value)} onBlur={maybeWriteDesc} />
                </div>
                {isMarket && (
                  <div className="field">
                    <span className="field-label">Category</span>
                    <select className="select" value={cat} onChange={e => setCat(e.target.value)}>
                      {cats.map(c => <option key={c}>{c}</option>)}
                    </select>
                  </div>
                )}
              </div>
              <div className="field">
                <span className="field-label" style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  Details
                  <button className="btn ghost sm" style={{ padding: "2px 8px", fontSize: 12, color: "var(--gold-dark)" }}
                          disabled={descBusy || !title.trim()} onClick={writeDesc}>
                    {descBusy ? "✦ writing…" : "✦ Rewrite"}
                  </button>
                </span>
                <div style={{ position: "relative" }}>
                  <textarea className="textarea" rows="2" placeholder={detailPh} value={detail}
                            onChange={e => setDetail(e.target.value)}
                            style={descBusy ? { opacity: 0.45 } : null}></textarea>
                  {descBusy && <span style={{ position: "absolute", left: 12, top: 10, fontSize: 13, color: "var(--gold-dark)", fontWeight: 600 }}>✦ writing it for you…</span>}
                </div>
                <span style={{ fontSize: 11.5, color: "var(--text-3)" }}>Written for you from the title — edit anything.</span>
              </div>
              {type !== "work" && type !== "job" && (
                <PhotoPicker photos={photos} setPhotos={setPhotos} kindHint={kindHint} title={title} />
              )}
              <button className="btn gold" style={{ justifyContent: "center", padding: "12px", fontSize: 15 }} disabled={!canPost} onClick={publish}>
                {type === "wanted" ? "Post request" : type === "job" ? "Post opening" : "Publish"}
              </button>
              <div style={{ fontSize: 12, color: "var(--text-3)", textAlign: "center" }}>Visible to everyone within 25 mi · free to post.</div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// Override the basic modal from the signed-in layer
if (window.RLS) window.RLS.PostListingModal = PostAnythingModal;
window.PostAnythingModal = PostAnythingModal;
