// Recursive MLS — Add/Edit (flagship) — registry-driven listing workspace.
// Every control is generated from window.RC_FIELDS (the same registry Field Studio edits),
// so a schema change in the Studio flows straight into this form. SABOR tenant.
const { useState } = React;
const inp = { width: "100%", boxSizing: "border-box", border: "1px solid #e2e0d8", borderRadius: 7, padding: "9px 11px", fontFamily: "inherit", fontSize: 13.5, color: "#1d241f", background: "#fff", outline: "none" };
const inpAffix = { position: "absolute", left: 11, top: "50%", transform: "translateY(-50%)", fontSize: 13.5, color: "#8a8e88", fontFamily: "'Space Mono', monospace" };
function AddEditWorkspace({ go }) {
  const F = window.RC_FIELDS, C = window.RC_COMPLIANCE, D = window.RC_DATA;
  const _p = new URLSearchParams(location.search);

  // ---- seed values (San Antonio / SABOR listing) ----
  const [vals, setVals] = useState({
    UnparsedAddress: "18 Elderwood", City: "San Antonio", StateOrProvince: "TX", PostalCode: "78248", UnitNumber: "",
    PropertyType: _p.get("ptype") || "Residential", PropertySubType: "SingleFamilyResidence", YearBuilt: 2016,
    BedroomsTotal: 4, BathroomsTotalInteger: 4, LivingArea: 3980, LotSizeAcres: 0.42, X_SABOR_GuardGated: true,
    ListPrice: 1295000, AssociationFee: 285, AssociationFeeFrequency: "Monthly", TaxAnnualAmount: 21400, BuyerAgencyCompensation: "",
    SecurityDeposit: 2600, LeaseTerm: "TwelveMonths", AvailabilityDate: "2026-08-01", FurnishedYN: false, PetsAllowed: ["Cats", "Dogs"],
    PublicRemarks: "Set behind the gates of a sought-after North San Antonio enclave, this 2016 custom home pairs a light-filled great room with a chef's kitchen and a resort backyard.",
    PrivateRemarks: "Seller prefers 45-day close. Alarm on the mudroom door.",
    PoolFeatures: ["InGround", "Heated", "Gunite"], Flooring: ["Wood", "Tile"], Cooling: ["CentralAir", "Zoned"],
    X_SABOR_WaterfrontName: "", X_SABOR_HorseProperty: false,
    ListAgentFullName: "Alex Morgan", ListOfficeName: "Recursive Realty", ListAgentDirectPhone: "(210) 555-0148", ListAgentEmail: "alex@recursiverealty.com",
    photos: D.gallery(3),
  });
  const set = (k, v) => setVals((s) => ({ ...s, [k]: v }));

  // ---- smart form: listing class + density (seeded by tweaks, live-editable in the header) ----
  const [listingClass, setListingClass] = useState(_p.get("class") === "Lease" ? "Lease" : "Sale");
  const density = _p.get("density") === "compact" ? "compact" : "comfortable";
  const gap = density === "compact" ? 9 : 13;

  // ---- autofill review state: address-first prefills carrying provenance, awaiting confirm ----
  const [suggested, setSuggested] = useState({
    YearBuilt: "record", LivingArea: "record", LotSizeAcres: "record", TaxAnnualAmount: "record",
    PoolFeatures: "photo", X_SABOR_GuardGated: "prior",
  });
  const confirmField = (k) => setSuggested((s) => { const n = { ...s }; delete n[k]; return n; });
  const acceptAll = () => setSuggested({});
  const suggestCount = Object.keys(suggested).length;

  // ---- status control ----
  const [statusKey, setStatusKey] = useState("ComingSoon");
  const status = F.statusByKey(statusKey);
  const [showStatus, setShowStatus] = useState(false);
  const [targetStatus] = useState("Active"); // required-for checklist target

  // ---- field filter toggle ----
  const [filter, setFilter] = useState("all"); // all | required | incomplete
  const isEmpty = (f) => { const v = vals[f.key]; return v === "" || v == null || (Array.isArray(v) && v.length === 0) || v === false; };
  // ---- smart-form visibility: business rules decide which fields show ----
  const inClass = (f) => F.forClass(f, listingClass);
  const condHidden = (f) => {
    if (f.key === "AssociationFeeFrequency") return !(Number(vals.AssociationFee) > 0); // only when there's an HOA fee
    if (f.key === "LotSizeAcres") return vals.PropertySubType === "Condominium";         // condos have no lot
    if (f.key === "PropertySubType") return !vals.PropertyType;
    return false;
  };
  const visibleField = (f) => inClass(f) && !condHidden(f);
  const hiddenForClass = F.fields.filter((f) => f.life === "active" && !inClass(f));
  const requiredFields = F.fields.filter((f) => f.required && f.life === "active" && visibleField(f));
  const incompleteReq = requiredFields.filter(isEmpty);

  // ---- compliance (flat RESO listing built from registry values) ----
  const listing = {
    PublicRemarks: vals.PublicRemarks, Media: vals.photos.map(() => ({ MediaCategory: "Photo" })),
    LivingArea: vals.LivingArea, YearBuilt: vals.YearBuilt, LotSizeAcres: vals.LotSizeAcres,
    ListOfficeName: vals.ListOfficeName, ListAgentFullName: vals.ListAgentFullName,
    ListAgentDirectPhone: vals.ListAgentDirectPhone, ListAgentEmail: vals.ListAgentEmail,
  };
  const violations = C.getViolations(listing), tips = C.getTips(listing);
  const sqft = C.verifySqft(`${vals.UnparsedAddress} ${vals.City} ${vals.StateOrProvince}`, vals.LivingArea);
  const [certified, setCertified] = useState(false);
  const highVios = violations.filter((v) => v.severity === "high").length;
  const sqftBlocks = sqft.state === "done" && sqft.sources.length > 0 && sqft.score < C.SQFT_MIN && !certified;
  const canPublish = highVios === 0 && !sqftBlocks && incompleteReq.length === 0;

  // ---- section nav flags ----
  const sectionMap = { "sec-details": "details", "sec-pricing": "pricing", "sec-desc": "desc", "sec-photos": "photos", "sec-features": "features", "sec-agent": "agent" };
  const flagFor = (secId) => {
    const step = secId; const v = violations.filter((x) => x.step === step).length, t = tips.filter((x) => x.step === step).length;
    const missing = F.bySection(sectionMap[secId] || "").filter((f) => f.required && visibleField(f) && isEmpty(f)).length;
    return { v, t, missing };
  };
  const [active, setActive] = useState("sec-details");
  const jump = (id) => { setActive(id); const el = document.getElementById(id); if (!el) return; let sc = el.parentElement; while (sc && sc.scrollHeight <= sc.clientHeight) sc = sc.parentElement; if (sc) sc.scrollTo({ top: sc.scrollTop + el.getBoundingClientRect().top - sc.getBoundingClientRect().top - 16, behavior: "smooth" }); };

  // ---- conflict banner ----
  const [conflict, setConflict] = useState(true);

  const secDefs = [
    { id: "sec-details", sec: "details" }, { id: "sec-pricing", sec: "pricing" }, { id: "sec-desc", sec: "desc" },
    { id: "sec-photos", sec: "photos" }, { id: "sec-features", sec: "features" }, { id: "sec-agent", sec: "agent" },
  ];

  const showField = (f) => {
    if (!visibleField(f)) return false;
    if (filter === "required") return f.required;
    if (filter === "incomplete") return f.required && isEmpty(f);
    return true;
  };

  return (
    <div style={{ padding: "0 0 60px" }}>
      {/* ===== sticky header ===== */}
      <div style={{ position: "sticky", top: 0, zIndex: 5, background: "#f4f3ef", padding: "16px 30px 12px", borderBottom: "1px solid #ebe9e1" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 14 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <button onClick={() => go && go("drafts")} style={iconBtn}><Icon name="arrow-left" size={17} color="#4a504a" /></button>
            <div>
              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                <h1 style={{ margin: 0, fontSize: 21, fontWeight: 600, letterSpacing: "-0.5px", color: "#1d241f" }}>{vals.UnparsedAddress || "New listing"}</h1>
                <StatusControl status={status} onOpen={() => setShowStatus(true)} />
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 4, fontSize: 12.5, color: "#8a8e88" }}>
                <span style={{ display: "inline-flex", alignItems: "center", gap: 5, color: "#1f8a5b" }}><Icon name="cloud" size={13} color="#1f8a5b" /> Saved 3s ago</span>
                <span style={{ color: "#e0ded6" }}>·</span>
                <span>{vals.City}, {vals.StateOrProvince} {vals.PostalCode}</span>
                <span style={{ color: "#e0ded6" }}>·</span>
                <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>{F.tenant.short} <span style={{ color: "#c4c7c1" }}>tenant</span></span>
              </div>
            </div>
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <ComplianceChip violations={violations} tips={tips} />
            <button style={btnOutline}><Icon name="check-check" size={15} color="#4a504a" /> Validate</button>
            <button style={btnOutline}>Save draft</button>
            <button style={{ ...btnPrimary, opacity: canPublish ? 1 : 0.5, cursor: canPublish ? "pointer" : "not-allowed" }} disabled={!canPublish}
              title={canPublish ? "" : "Resolve blockers before submitting to the MLS"}>
              <Icon name={canPublish ? "send" : "lock"} size={15} color="#fff" /> Save & submit
            </button>
          </div>
        </div>
        {/* listing-class segmented control + field filter toggle + live counts */}
        <div style={{ display: "flex", alignItems: "center", gap: 14, marginTop: 12, flexWrap: "wrap" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontSize: 11, fontWeight: 600, letterSpacing: ".4px", textTransform: "uppercase", color: "#a8aca6" }}>Listing type</span>
            <div style={{ display: "flex", background: "#fff", borderRadius: 8, padding: 3, boxShadow: "inset 0 0 0 1px rgba(0,0,0,.07)" }}>
              {F.listingClasses.map((c) => (
                <button key={c} onClick={() => setListingClass(c)} style={{ display: "inline-flex", alignItems: "center", gap: 6, border: 0, background: listingClass === c ? "#006747" : "transparent", color: listingClass === c ? "#fff" : "#6b706a", fontFamily: "inherit", fontSize: 12.5, fontWeight: 600, padding: "6px 14px", borderRadius: 6, cursor: "pointer" }}>
                  <Icon name={c === "Sale" ? "tag" : "key-round"} size={13} color={listingClass === c ? "#fff" : "#a8aca6"} /> For {c === "Sale" ? "sale" : "lease"}
                </button>
              ))}
            </div>
          </div>
          <div style={{ width: 1, height: 22, background: "#e2e0d8" }} />
          <div style={{ display: "flex", background: "#fff", borderRadius: 8, padding: 3, boxShadow: "inset 0 0 0 1px rgba(0,0,0,.07)" }}>
            {[["all", "All fields"], ["required", `Required · ${requiredFields.length}`], ["incomplete", `Incomplete · ${incompleteReq.length}`]].map(([k, lbl]) => (
              <button key={k} onClick={() => setFilter(k)} style={{ border: 0, background: filter === k ? "#eef4f1" : "transparent", color: filter === k ? "#006747" : "#6b706a", fontFamily: "inherit", fontSize: 12.5, fontWeight: 600, padding: "6px 13px", borderRadius: 6, cursor: "pointer" }}>{lbl}</button>
            ))}
          </div>
          <span style={{ fontSize: 12.5, color: "#8a8e88" }}><strong style={{ color: incompleteReq.length ? "#c0612f" : "#1f8a5b" }}>{incompleteReq.length} to go</strong> before Active</span>
          {hiddenForClass.length > 0 && (
            <span title={hiddenForClass.map((f) => f.label).join(", ")} style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 12, color: "#6b706a", background: "#eef3fb", borderRadius: 999, padding: "4px 11px" }}>
              <Icon name="eye-off" size={13} color="#2f6bd0" /> {hiddenForClass.length} {listingClass === "Lease" ? "sale-only" : "lease-only"} fields hidden
            </span>
          )}
          {suggestCount > 0 && (
            <span style={{ marginLeft: "auto", display: "inline-flex", alignItems: "center", gap: 8, fontSize: 12.5, color: "#9a6a12" }}>
              <Icon name="wand-sparkles" size={14} color="#9a6a12" /> {suggestCount} autofilled fields to review
              <button onClick={acceptAll} style={{ ...btnTiny, background: "#006747", color: "#fff", border: 0 }}>Accept all</button>
            </span>
          )}
        </div>
      </div>

      <div style={{ padding: "16px 30px 0" }}>
        {conflict && (
          <div style={{ display: "flex", alignItems: "center", gap: 12, background: "#fdf4f3", border: "1px solid #f2d6d2", borderRadius: 8, padding: "11px 14px", marginBottom: 16 }}>
            <Icon name="git-merge" size={17} color="#b3261e" />
            <span style={{ fontSize: 13, color: "#7a2420", flex: 1 }}>This listing changed while you were editing — <strong>3 conflicting fields</strong> (List price, Status, Public remarks).</span>
            <button style={{ ...btnTiny, border: "1px solid #e2b6b0", background: "#fff", color: "#b3261e" }}>Resolve conflicts</button>
            <button onClick={() => setConflict(false)} style={iconBtnSm}><Icon name="x" size={14} color="#8a8e88" /></button>
          </div>
        )}

        <div className="le-grid" style={{ display: "grid", gridTemplateColumns: "196px 1fr", gap: 22, alignItems: "start" }}>
          {/* ===== section nav ===== */}
          <div className="le-nav" style={{ position: "sticky", top: 150, display: "flex", flexDirection: "column", gap: 2 }}>
            {secDefs.map((s) => {
              const def = F.sections.find((x) => x.id === s.sec); const fl = flagFor(s.id);
              return (
                <a key={s.id} href={`#${s.id}`} onClick={(e) => { e.preventDefault(); jump(s.id); }}
                  style={{ display: "flex", alignItems: "center", gap: 10, padding: "9px 11px", borderRadius: 7, textDecoration: "none", fontSize: 13.5, fontWeight: active === s.id ? 600 : 400, color: active === s.id ? "#006747" : "#4a504a", background: active === s.id ? "#eef4f1" : "transparent" }}>
                  <Icon name={def.icon} size={16} color={active === s.id ? "#006747" : "#a8aca6"} /> <span style={{ flex: 1 }}>{def.label}</span>
                  {fl.v > 0 && <span style={badgeDot("#b3261e")}>{fl.v}</span>}
                  {fl.v === 0 && fl.missing > 0 && <span style={badgeDot("#2f6bd0")}>{fl.missing}</span>}
                  {fl.v === 0 && fl.missing === 0 && fl.t > 0 && <span style={{ width: 7, height: 7, borderRadius: "50%", background: "#d97757" }} />}
                </a>
              );
            })}
            <div style={{ borderTop: "1px solid #ececec", margin: "10px 4px 0", paddingTop: 10 }}>
              <button onClick={() => go && go("fieldstudio")} style={{ display: "flex", alignItems: "center", gap: 9, width: "100%", background: "transparent", border: 0, padding: "8px 11px", borderRadius: 7, cursor: "pointer", fontFamily: "inherit", fontSize: 12.5, color: "#6b706a", textAlign: "left" }}>
                <Icon name="sliders-horizontal" size={15} color="#a8aca6" /> Form comes from the tenant layout · <span style={{ color: "#006747", fontWeight: 600 }}>Field Studio</span>
              </button>
            </div>
          </div>

          {/* ===== form | rail ===== */}
          <div className="le-split" style={{ display: "grid", gridTemplateColumns: "minmax(0,1fr) 372px", gap: 22, alignItems: "start", minWidth: 0 }}>
            <div style={{ display: "flex", flexDirection: "column", gap: 16, minWidth: 0 }}>
              {secDefs.map((s) => {
                const def = F.sections.find((x) => x.id === s.sec);
                const secFields = F.bySection(s.sec).filter(showField);
                return (
                  <SectionCard key={s.id} id={s.id} title={def.label} flag={flagFor(s.id)}>
                    {s.sec === "photos" ? (
                      <PhotoStrip photos={vals.photos} onManage={() => go && go("media")} suggested={!!suggested.PoolFeatures} />
                    ) : secFields.length === 0 ? (
                      <div style={{ fontSize: 12.5, color: "#a8aca6", padding: "4px 0" }}>No {filter === "incomplete" ? "incomplete required" : filter} fields in this section.</div>
                    ) : (
                      <div style={{ display: "grid", gridTemplateColumns: "repeat(12, 1fr)", gap: gap, alignItems: "start" }}>
                        {secFields.map((f) => (
                          <FieldControl key={f.key} f={f} vals={vals} set={set} cls={listingClass} suggested={suggested[f.key]} onConfirm={() => confirmField(f.key)} />
                        ))}
                        {s.sec === "details" && <div style={{ gridColumn: "span 12" }}><SqftConfidence result={sqft} certified={certified} onCertify={setCertified} /></div>}
                      </div>
                    )}
                  </SectionCard>
                );
              })}
            </div>

            {/* ===== right rail ===== */}
            <div className="le-preview" style={{ position: "sticky", top: 150, display: "flex", flexDirection: "column", gap: 16 }}>
              <CompliancePanel violations={violations} tips={tips} onJump={(step) => jump(step)} />
              <RequiredForStatus target={targetStatus} vals={vals} isEmpty={isEmpty} onJump={jump} />
              <AIComposer vals={vals} onInsert={(text) => set("PublicRemarks", text)} />
              <BuyerPreview vals={vals} cls={listingClass} statusName={status.name} statusTone={status.tone} />
            </div>
          </div>
        </div>
      </div>

      {showStatus && <StatusTransitionModal current={status} onClose={() => setShowStatus(false)} onPick={(k) => { setStatusKey(k); setShowStatus(false); }} />}
    </div>
  );
}

/* ============================ field control ============================ */
function FieldControl({ f, vals, set, suggested, onConfirm, cls }) {
  const F = window.RC_FIELDS;
  const v = vals[f.key];
  const disabled = !!f.backendUnsupported;
  const locked = !!f.locked;
  const isRent = f.key === "ListPrice" && cls === "Lease";
  const displayLabel = isRent ? "Monthly rent" : f.label;
  const span = { gridColumn: `span ${Math.min(12, f.span || 6)}` };
  const suggBorder = suggested ? { boxShadow: "0 0 0 2px #f2e2b8", background: "#fefcf4" } : null;

  const head = (
    <div style={{ display: "flex", alignItems: "center", gap: 7, minHeight: 18 }}>
      <span style={{ fontSize: 11.5, fontWeight: 600, color: "#6b706a" }}>{displayLabel}</span>
      {f.required && <span style={{ color: "#c0612f", fontSize: 12, lineHeight: 1 }}>*</span>}
      <span style={{ flex: 1 }} />
      {suggested && <SourceChip origin={suggested} />}
      {f.agentOnly && <span title="Agent-only — not shown to the public" style={{ display: "inline-flex" }}><Icon name="eye-off" size={12} color="#a8aca6" /></span>}
      {locked && <span title={f.lockReason}><Icon name="lock" size={12} color="#9a6a12" /></span>}
      <ProvChip prov={f.provenance} size="xs" withLabel={false} />
    </div>
  );

  const control = () => {
    if (disabled) return <div style={{ ...inp, color: "#a8aca6", background: "#f6f5f1", display: "flex", alignItems: "center", gap: 7 }}><Icon name="ban" size={13} color="#b0b4ad" /> Not supported on {f.backendUnsupported}</div>;
    switch (f.type) {
      case "textarea": {
        const cnt = (v || "").length;
        return (<div>
          <textarea disabled={locked} value={v || ""} onChange={(e) => set(f.key, e.target.value)} style={{ ...inp, ...suggBorder, height: f.key === "PublicRemarks" ? 96 : 64, resize: "vertical", lineHeight: 1.5, fontFamily: "inherit" }} />
          {f.maxLength && <div style={{ textAlign: "right", fontSize: 11, color: cnt > f.maxLength ? "#b3261e" : "#a8aca6", marginTop: 3 }}>{cnt}/{f.maxLength}</div>}
        </div>);
      }
      case "money": return (<div style={{ position: "relative" }}><span style={inpAffix}>$</span><input disabled={locked} type="number" value={v ?? ""} onChange={(e) => set(f.key, e.target.value === "" ? "" : Number(e.target.value))} style={{ ...inp, ...suggBorder, paddingLeft: 24, paddingRight: isRent ? 42 : 11, fontFamily: "'Space Mono', monospace", fontWeight: f.key === "ListPrice" ? 700 : 400, background: locked ? "#f6f5f1" : "#fff" }} />{isRent && <span style={{ position: "absolute", right: 11, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "#8a8e88" }}>/mo</span>}</div>);
      case "number": return <input disabled={locked} type="number" value={v ?? ""} min={f.min} max={f.max} onChange={(e) => set(f.key, e.target.value === "" ? "" : Number(e.target.value))} style={{ ...inp, ...suggBorder }} />;
      case "date": return <input disabled={locked} type="date" value={v || ""} onChange={(e) => set(f.key, e.target.value)} style={{ ...inp, ...suggBorder, fontFamily: "inherit" }} />;
      case "boolean": return <TriState value={v} onChange={(nv) => set(f.key, nv)} style={suggBorder} />;
      case "enum": {
        let opts = F.activeLookup(f.lookup);
        if (f.dependsOn) opts = opts.filter((o) => !o.parent || o.parent === vals[f.dependsOn]);
        return (<div style={{ position: "relative" }}>
          <select value={v || ""} onChange={(e) => set(f.key, e.target.value)} style={{ ...inp, ...suggBorder, appearance: "none", paddingRight: 30, cursor: "pointer" }}>
            <option value="">—</option>
            {opts.map((o) => <option key={o.key} value={o.key}>{o.label}</option>)}
          </select>
          <span style={{ position: "absolute", right: 10, top: "50%", transform: "translateY(-50%)", pointerEvents: "none" }}><Icon name="chevron-down" size={15} color="#8a8e88" /></span>
        </div>);
      }
      case "multi": return <MultiChips field={f} value={v || []} onChange={(nv) => set(f.key, nv)} style={suggBorder} />;
      default: return <input disabled={locked} value={v || ""} onChange={(e) => set(f.key, e.target.value)} style={{ ...inp, ...suggBorder, background: locked ? "#f6f5f1" : "#fff" }} />;
    }
  };

  return (
    <label style={{ ...span, display: "flex", flexDirection: "column", gap: 6, minWidth: 0 }}>
      {head}
      {control()}
      {locked && <span style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 11, color: "#9a6a12" }}><Icon name="key-round" size={11} color="#9a6a12" /> Locked — <a href="#" onClick={(e) => e.preventDefault()} style={{ color: "#006747", fontWeight: 600, textDecoration: "none" }}>request change</a></span>}
      {suggested && !locked && (
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <button onClick={(e) => { e.preventDefault(); onConfirm(); }} style={{ ...btnTiny, background: "#eef4f1", color: "#006747", border: "1px solid #cfe3d8" }}><Icon name="check" size={12} color="#006747" /> Confirm</button>
          <span style={{ fontSize: 11, color: "#a8aca6" }}>or edit to accept</span>
        </div>
      )}
      {f.note && !suggested && !locked && <span style={{ fontSize: 10.5, color: "#a8aca6", lineHeight: 1.4 }}>{f.note}</span>}
    </label>
  );
}

function TriState({ value, onChange, style }) {
  const opts = [["Yes", true], ["No", false], ["—", null]];
  return (
    <div style={{ display: "flex", borderRadius: 7, overflow: "hidden", boxShadow: "inset 0 0 0 1px #e2e0d8", ...style }}>
      {opts.map(([lbl, val], i) => {
        const on = value === val;
        return <button key={lbl} type="button" onClick={() => onChange(val)} style={{ flex: 1, border: 0, borderLeft: i ? "1px solid #eceae2" : 0, background: on ? "#eef4f1" : "#fff", color: on ? "#006747" : "#8a8e88", fontFamily: "inherit", fontWeight: on ? 600 : 400, fontSize: 13, padding: "9px 0", cursor: "pointer" }}>{lbl}</button>;
      })}
    </div>
  );
}

function MultiChips({ field, value, onChange, style }) {
  const F = window.RC_FIELDS;
  const [open, setOpen] = useState(false);
  const opts = F.activeLookup(field.lookup);
  const label = (k) => (opts.find((o) => o.key === k) || {}).label || k;
  const toggle = (k) => onChange(value.includes(k) ? value.filter((x) => x !== k) : [...value, k]);
  return (
    <div style={{ position: "relative" }}>
      <div onClick={() => setOpen(!open)} style={{ ...inp, ...style, minHeight: 38, height: "auto", display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center", cursor: "pointer", paddingTop: 6, paddingBottom: 6 }}>
        {value.length === 0 && <span style={{ color: "#b0b4ad" }}>Select…</span>}
        {value.map((k) => (
          <span key={k} style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 12, fontWeight: 500, color: "#006747", background: "#eef4f1", border: "1px solid #cfe3d8", borderRadius: 999, padding: "3px 6px 3px 9px" }}>
            {label(k)}<span onClick={(e) => { e.stopPropagation(); toggle(k); }} style={{ display: "inline-flex", cursor: "pointer" }}><Icon name="x" size={12} color="#4f8a6c" /></span>
          </span>
        ))}
        <span style={{ marginLeft: "auto" }}><Icon name="chevron-down" size={15} color="#8a8e88" /></span>
      </div>
      {open && (
        <div style={{ position: "absolute", zIndex: 8, top: "calc(100% + 4px)", left: 0, right: 0, background: "#fff", borderRadius: 8, boxShadow: "0 8px 24px rgba(0,0,0,.14), inset 0 0 0 1px rgba(0,0,0,.08)", padding: 6, maxHeight: 200, overflowY: "auto" }}>
          {opts.map((o) => { const on = value.includes(o.key); return (
            <div key={o.key} onClick={() => toggle(o.key)} className="rc-row" style={{ display: "flex", alignItems: "center", gap: 9, padding: "7px 9px", borderRadius: 6, cursor: "pointer" }}>
              <span style={{ width: 15, height: 15, borderRadius: 4, background: on ? "#006747" : "#fff", boxShadow: on ? "none" : "inset 0 0 0 1px #d4d2c8", display: "flex", alignItems: "center", justifyContent: "center", flex: "none" }}>{on && <Icon name="check" size={11} color="#fff" />}</span>
              <span style={{ fontSize: 13, color: "#1d241f" }}>{o.label}</span>
            </div>
          ); })}
        </div>
      )}
    </div>
  );
}

/* ============================ header bits ============================ */
function StatusControl({ status, onOpen }) {
  const tones = { new: { bg: "#006747", fg: "#fff" }, active: { bg: "#e8f4ee", fg: "#1f8a5b" }, pending: { bg: "#fbf2dc", fg: "#9a6a12" }, neutral: { bg: "#f0efe9", fg: "#6b706a" } };
  const t = tones[status.tone] || tones.neutral;
  return (
    <button onClick={onOpen} style={{ display: "inline-flex", alignItems: "center", gap: 7, background: t.bg, color: t.fg, border: 0, borderRadius: 999, padding: "5px 10px 5px 12px", fontFamily: "inherit", fontSize: 12.5, fontWeight: 600, cursor: "pointer" }}>
      {status.name} <Icon name="chevron-down" size={14} color={t.fg} />
    </button>
  );
}
function ComplianceChip({ violations, tips }) {
  const has = violations.length, tip = tips.length;
  const bg = has ? "#fbe9e7" : tip ? "#faf0e8" : "#e8f4ee", fg = has ? "#b3261e" : tip ? "#c0612f" : "#1f8a5b";
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 7, padding: "8px 12px", borderRadius: 999, background: bg }}>
      <Icon name={has ? "shield-alert" : tip ? "lightbulb" : "shield-check"} size={15} color={fg} />
      <span style={{ fontSize: 12.5, fontWeight: 600, color: fg }}>{has ? `${has} to fix` : tip ? `${tip} tips` : "Compliant"}</span>
    </div>
  );
}

/* ============================ right-rail panels ============================ */
function RequiredForStatus({ target, vals, isEmpty, onJump }) {
  const F = window.RC_FIELDS;
  const req = F.reqMatrix[target] || {};
  const rows = F.reqMatrixFields.filter((k) => req[k]);
  const secOf = (k) => (F.byKey(k) ? "sec-" + F.byKey(k).section : "sec-photos");
  const ok = (k) => k === "Media" ? vals.photos.length > 0 : k === "ClosePrice" ? false : !isEmpty(F.byKey(k) || { key: k });
  const done = rows.filter(ok).length;
  return (
    <div style={panel}>
      <div style={{ padding: "13px 16px", borderBottom: "1px solid #f1f0ea", display: "flex", alignItems: "center", gap: 8 }}>
        <Icon name="list-checks" size={15} color="#2f6bd0" />
        <h3 style={{ margin: 0, fontSize: 13.5, fontWeight: 600, color: "#1d241f", flex: 1 }}>Required for <span style={{ color: "#2f6bd0" }}>{target}</span></h3>
        <span style={{ fontFamily: "'Space Mono', monospace", fontSize: 12, color: done === rows.length ? "#1f8a5b" : "#8a8e88" }}>{done}/{rows.length}</span>
      </div>
      <div style={{ padding: "6px 8px" }}>
        {rows.map((k) => { const label = k === "Media" ? "≥1 photo" : k === "ClosePrice" ? "Close price & date" : (F.byKey(k) || {}).label || k; const good = ok(k); return (
          <div key={k} className="rc-row" onClick={() => onJump(secOf(k))} style={{ display: "flex", alignItems: "center", gap: 9, padding: "7px 8px", borderRadius: 6, cursor: "pointer" }}>
            <Icon name={good ? "check-circle-2" : "circle"} size={16} color={good ? "#1f8a5b" : "#c4c7c1"} />
            <span style={{ fontSize: 12.5, color: good ? "#8a8e88" : "#1d241f", textDecoration: good ? "line-through" : "none", flex: 1 }}>{label}</span>
            {!good && <ProvChip prov={(F.byKey(k) || { provenance: "standard" }).provenance} size="xs" withLabel={false} />}
          </div>
        ); })}
      </div>
    </div>
  );
}

function AIComposer({ vals, onInsert }) {
  const [tone, setTone] = useState("Professional");
  const [out, setOut] = useState("");
  const [busy, setBusy] = useState(false);
  const generate = () => {
    setBusy(true);
    setTimeout(() => {
      const beds = vals.BedroomsTotal, ba = vals.BathroomsTotalInteger, sq = vals.LivingArea;
      const pool = (vals.PoolFeatures || []).length ? " a heated in-ground pool," : "";
      const base = {
        Professional: `Sited in a guard-gated North San Antonio enclave, this ${vals.YearBuilt} custom residence offers ${beds} bedrooms, ${ba} baths, and ${sq.toLocaleString()} sqft of refined living. A light-filled great room opens to a chef's kitchen and${pool} a private resort backyard.`,
        Warm: `Welcome home. Tucked behind the gates of a beloved San Antonio neighborhood, this ${beds}-bed, ${ba}-bath charmer wraps ${sq.toLocaleString()} sqft of easy living around${pool} a backyard made for slow weekends.`,
        Punchy: `Gated. Custom. ${sq.toLocaleString()} sqft. ${beds} beds, ${ba} baths,${pool} and a backyard that ends the search. Built ${vals.YearBuilt}.`,
      };
      setOut(base[tone]); setBusy(false);
    }, 700);
  };
  return (
    <div style={panel}>
      <div style={{ padding: "13px 16px", borderBottom: "1px solid #f1f0ea", display: "flex", alignItems: "center", gap: 8 }}>
        <span style={{ width: 24, height: 24, borderRadius: 6, background: "#eef4f1", display: "flex", alignItems: "center", justifyContent: "center" }}><Icon name="sparkles" size={14} color="#006747" /></span>
        <h3 style={{ margin: 0, fontSize: 13.5, fontWeight: 600, color: "#1d241f", flex: 1 }}>AI description</h3>
        <span style={{ fontSize: 10.5, color: "#a8aca6" }}>from your facts</span>
      </div>
      <div style={{ padding: 14, display: "flex", flexDirection: "column", gap: 10 }}>
        <div style={{ display: "flex", gap: 6 }}>
          {["Professional", "Warm", "Punchy"].map((t) => (
            <button key={t} onClick={() => setTone(t)} style={{ flex: 1, border: 0, background: tone === t ? "#eef4f1" : "#f6f5f1", color: tone === t ? "#006747" : "#6b706a", fontFamily: "inherit", fontSize: 12, fontWeight: 600, padding: "6px 0", borderRadius: 6, cursor: "pointer" }}>{t}</button>
          ))}
        </div>
        {out ? (
          <div style={{ fontSize: 12.5, color: "#4a504a", lineHeight: 1.55, background: "#faf9f5", borderRadius: 7, padding: 11 }}>{out}
            <div style={{ display: "inline-flex", alignItems: "center", gap: 5, marginTop: 8, fontSize: 11, color: "#1f8a5b" }}><Icon name="shield-check" size={12} color="#1f8a5b" /> Passed compliance pre-scan</div>
          </div>
        ) : (
          <div style={{ fontSize: 12, color: "#a8aca6", lineHeight: 1.5 }}>Generate PublicRemarks from the facts you've entered. Review before inserting — AI copy is a draft, not authoritative.</div>
        )}
        <div style={{ display: "flex", gap: 8 }}>
          <button onClick={generate} disabled={busy} style={{ ...btnPrimary, flex: 1, justifyContent: "center", opacity: busy ? 0.6 : 1 }}>
            {busy ? <><Icon name="loader" size={14} color="#fff" style={{ animation: "rc-spin 1s linear infinite" }} /> Writing…</> : <><Icon name={out ? "refresh-cw" : "sparkles"} size={14} color="#fff" /> {out ? "Regenerate" : "Generate"}</>}
          </button>
          {out && <button onClick={() => onInsert(out)} style={{ ...btnOutline, flex: 1, justifyContent: "center" }}>Insert</button>}
        </div>
      </div>
    </div>
  );
}

function BuyerPreview({ vals, cls, statusName, statusTone }) {
  const D = window.RC_DATA, F = window.RC_FIELDS;
  const isRent = cls === "Lease";
  const feat = [...(vals.PoolFeatures || []), ...(vals.Flooring || [])];
  return (
    <div>
      <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: "uppercase", letterSpacing: "1.2px", color: "#a8aca6", marginBottom: 9, display: "flex", alignItems: "center", gap: 6 }}><Icon name="eye" size={13} color="#a8aca6" /> Live preview — buyer view</div>
      <div style={{ background: "#fff", borderRadius: 4, boxShadow: "0 2px 12px rgba(0,0,0,.08), inset 0 0 0 1px rgba(0,0,0,.06)", overflow: "hidden" }}>
        <div style={{ position: "relative", aspectRatio: "3/2", backgroundImage: `url(${vals.photos[0]})`, backgroundSize: "cover", backgroundPosition: "center" }}>
          <span style={{ position: "absolute", top: 10, left: 10 }}><Pill tone={statusTone === "active" ? "active" : statusTone === "pending" ? "pending" : "new"}>{statusName}{isRent ? " · For lease" : ""}</Pill></span>
          <span style={{ position: "absolute", bottom: 10, right: 10, fontSize: 11, color: "#fff", background: "rgba(0,0,0,.55)", padding: "2px 8px", borderRadius: 3 }}>1 / {vals.photos.length}</span>
        </div>
        <div style={{ padding: 16 }}>
          <div style={{ fontFamily: "'Space Mono', monospace", fontSize: 22, fontWeight: 700, color: "#1d241f" }}>{vals.ListPrice ? D.usd(vals.ListPrice) : "$—"}{isRent && <span style={{ fontSize: 13, fontWeight: 400, color: "#8a8e88" }}>/mo</span>}</div>
          <div style={{ display: "flex", gap: 14, fontSize: 13, color: "#4a504a", margin: "8px 0 10px" }}>
            <span><strong>{vals.BedroomsTotal || "—"}</strong> bd</span><span style={{ color: "#e0ded6" }}>·</span>
            <span><strong>{vals.BathroomsTotalInteger || "—"}</strong> ba</span><span style={{ color: "#e0ded6" }}>·</span>
            <span><strong>{vals.LivingArea ? vals.LivingArea.toLocaleString() : "—"}</strong> sqft</span>
          </div>
          <div style={{ fontSize: 14, fontWeight: 600, color: "#1d241f" }}>{vals.UnparsedAddress}</div>
          <div style={{ fontSize: 13, color: "#8a8e88", marginTop: 2 }}>{vals.City}, {vals.StateOrProvince} {vals.PostalCode}</div>
          <p style={{ fontSize: 12.5, color: "#6b706a", lineHeight: 1.55, margin: "11px 0 0", display: "-webkit-box", WebkitLineClamp: 3, WebkitBoxOrient: "vertical", overflow: "hidden" }}>{vals.PublicRemarks}</p>
        </div>
      </div>
    </div>
  );
}

function PhotoStrip({ photos, onManage, suggested }) {
  return (
    <div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 8 }}>
        {photos.map((p, i) => (
          <div key={i} style={{ position: "relative", aspectRatio: "4/3", borderRadius: 4, backgroundImage: `url(${p})`, backgroundSize: "cover", backgroundPosition: "center" }}>
            {i === 0 && <span style={{ position: "absolute", top: 6, left: 6, fontSize: 9.5, fontWeight: 600, textTransform: "uppercase", letterSpacing: ".5px", background: "rgba(0,0,0,.6)", color: "#fff", padding: "2px 6px", borderRadius: 3 }}>Cover</span>}
          </div>
        ))}
        <div onClick={onManage} style={{ aspectRatio: "4/3", borderRadius: 4, border: "1.5px dashed #d9d7cd", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 5, color: "#8a8e88", cursor: "pointer" }}>
          <Icon name="upload" size={18} color="#8a8e88" /><span style={{ fontSize: 11.5 }}>Manage</span>
        </div>
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 10, flexWrap: "wrap" }}>
        <span style={{ fontSize: 12, color: "#8a8e88" }}><strong style={{ color: "#4a504a" }}>{photos.length} of 12</strong> min photos · max 50</span>
        {suggested && <span style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 11.5, color: "#9a6a12", background: "#fbf2dc", borderRadius: 999, padding: "3px 9px" }}><Icon name="sparkles" size={12} color="#9a6a12" /> 4 AI feature tags to review</span>}
        <button onClick={onManage} style={{ ...btnTiny, marginLeft: "auto", border: "1px solid #e2e0d8", background: "#fff", color: "#4a504a" }}><Icon name="images" size={12} color="#4a504a" /> Open media manager</button>
      </div>
    </div>
  );
}

/* ============================ status transition modal ============================ */
function StatusTransitionModal({ current, onClose, onPick }) {
  const F = window.RC_FIELDS;
  const [sel, setSel] = useState(null);
  const allowed = (current.next || []).map((k) => F.statusByKey(k)).filter(Boolean);
  const selStatus = sel ? F.statusByKey(sel) : null;
  return (
    <div onClick={onClose} style={overlay}>
      <div onClick={(e) => e.stopPropagation()} style={{ ...modal, width: 520 }}>
        <div style={modalHead}>
          <div><div style={{ fontSize: 16, fontWeight: 600, color: "#1d241f" }}>Change status</div><div style={{ fontSize: 12.5, color: "#8a8e88", marginTop: 2 }}>From <strong>{current.name}</strong> · only allowed transitions shown</div></div>
          <button onClick={onClose} style={iconBtnSm}><Icon name="x" size={16} color="#8a8e88" /></button>
        </div>
        <div style={{ padding: 18 }}>
          {allowed.length === 0 && <div style={{ fontSize: 13, color: "#8a8e88" }}>No further transitions available from this status for your role.</div>}
          <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            {allowed.map((s) => (
              <button key={s.key} onClick={() => setSel(s.key)} style={{ display: "flex", alignItems: "center", gap: 11, padding: "12px 14px", borderRadius: 9, border: sel === s.key ? "1.5px solid #006747" : "1px solid #e6e4dc", background: sel === s.key ? "#f5f9f7" : "#fff", cursor: "pointer", textAlign: "left", fontFamily: "inherit" }}>
                <Icon name={sel === s.key ? "check-circle-2" : "circle"} size={18} color={sel === s.key ? "#006747" : "#c4c7c1"} />
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: "#1d241f" }}>{s.name}</div>
                  <div style={{ fontSize: 11.5, color: "#8a8e88", marginTop: 2 }}>Maps to RESO <span style={{ fontFamily: "'Space Mono', monospace" }}>{s.std}</span>{!s.roles.agent && " · staff only"}</div>
                </div>
                {!s.roles.agent && <Icon name="lock" size={14} color="#9a6a12" />}
              </button>
            ))}
          </div>
          {selStatus && (selStatus.auto || selStatus.companion) && (
            <div style={{ marginTop: 14, borderTop: "1px solid #f1f0ea", paddingTop: 14 }}>
              {selStatus.auto && <div style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12.5, color: "#2f6bd0", background: "#eef3fb", borderRadius: 7, padding: "9px 11px" }}><Icon name="calendar-clock" size={14} color="#2f6bd0" /> Will automatically become Active on <strong>Jul 22, 2026</strong>.</div>}
              {selStatus.companion && (
                <div style={{ marginTop: 10, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
                  {selStatus.companion.map((c) => (
                    <label key={c} style={{ display: "flex", flexDirection: "column", gap: 5 }}>
                      <span style={{ fontSize: 11.5, fontWeight: 600, color: "#6b706a" }}>{c === "ClosePrice" ? "Close price" : "Close date"} <span style={{ color: "#c0612f" }}>*</span></span>
                      <input style={inp} placeholder={c === "ClosePrice" ? "$1,250,000" : "mm/dd/yyyy"} />
                    </label>
                  ))}
                </div>
              )}
            </div>
          )}
          <div style={{ marginTop: 16, display: "flex", alignItems: "center", gap: 8, fontSize: 11.5, color: "#a8aca6" }}>
            <Icon name="history" size={13} color="#a8aca6" /> Last change: Coming Soon set by Alex Morgan · Jul 15, 9:04 AM
          </div>
        </div>
        <div style={{ padding: "14px 18px", borderTop: "1px solid #f1f0ea", display: "flex", justifyContent: "flex-end", gap: 10 }}>
          <button onClick={onClose} style={btnOutline}>Cancel</button>
          <button onClick={() => sel && onPick(sel)} disabled={!sel} style={{ ...btnPrimary, opacity: sel ? 1 : 0.5 }}>Apply status</button>
        </div>
      </div>
    </div>
  );
}

/* ============================ shared card + styles ============================ */
function SectionCard({ id, title, children, flag }) {
  const f = flag || { v: 0, t: 0, missing: 0 };
  return (
    <section id={id} style={{ background: "#fff", borderRadius: 3, boxShadow: "inset 0 0 0 1px rgba(0,0,0,.07)", scrollMarginTop: 150 }}>
      <div style={{ padding: "13px 18px", borderBottom: "1px solid #f1f0ea", display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10 }}>
        <h2 style={{ margin: 0, fontSize: 15, fontWeight: 600, color: "#1d241f" }}>{title}</h2>
        <div style={{ display: "flex", gap: 7 }}>
          {f.v > 0 && <span style={pillFlag("#b3261e", "#fbe9e7")}><Icon name="shield-alert" size={12} color="#b3261e" /> {f.v}</span>}
          {f.missing > 0 && <span style={pillFlag("#2f6bd0", "#eef3fb")}><Icon name="asterisk" size={12} color="#2f6bd0" /> {f.missing}</span>}
          {f.t > 0 && <span style={pillFlag("#c0612f", "#faf0e8")}><Icon name="lightbulb" size={12} color="#c0612f" /> {f.t}</span>}
          {f.v === 0 && f.t === 0 && f.missing === 0 && <Icon name="circle-check" size={16} color="#1f8a5b" />}
        </div>
      </div>
      <div style={{ padding: 18 }}>{children}</div>
    </section>
  );
}

const iconBtn = { border: "1px solid #e2e0d8", background: "#fff", borderRadius: 7, width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer" };
const iconBtnSm = { border: 0, background: "transparent", cursor: "pointer", display: "flex", padding: 4 };
const btnTiny = { display: "inline-flex", alignItems: "center", gap: 5, fontFamily: "inherit", fontSize: 11.5, fontWeight: 600, padding: "5px 10px", borderRadius: 6, cursor: "pointer" };
const badgeDot = (bg) => ({ minWidth: 16, height: 16, borderRadius: 999, background: bg, color: "#fff", fontSize: 10, fontWeight: 700, display: "flex", alignItems: "center", justifyContent: "center", padding: "0 4px", fontFamily: "'Space Mono', monospace" });
const pillFlag = (fg, bg) => ({ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 11, fontWeight: 600, color: fg, background: bg, borderRadius: 999, padding: "3px 9px" });
const panel = { background: "#fff", borderRadius: 3, boxShadow: "inset 0 0 0 1px rgba(0,0,0,.07)", overflow: "hidden" };
const overlay = { position: "fixed", inset: 0, background: "rgba(20,28,22,.42)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 40, padding: 20 };
const modal = { background: "#fff", borderRadius: 12, boxShadow: "0 24px 60px rgba(0,0,0,.28)", maxHeight: "88vh", overflowY: "auto" };
const modalHead = { padding: "16px 18px", borderBottom: "1px solid #f1f0ea", display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 10 };

window.AddEditWorkspace = AddEditWorkspace;
