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

/* ────────────────────────────────────────────────
   Data loading — fetch the property JSON by slug, exactly
   like the original page (/content/properties/{slug}.json).
   ──────────────────────────────────────────────── */
function getSlug() {
  const parts = window.location.pathname.split("/").filter(Boolean);
  let last = (parts[parts.length - 1] || "").replace(/\.html$/, "");
  if (last && last !== "property" && last !== "property-view") {
    return decodeURIComponent(last);
  }
  return new URLSearchParams(window.location.search).get("slug");
}

// Parse a money/number value that may be a string like "80000" or "~1,000".
function num(v) {
  if (v == null || v === "") return null;
  const n = Number(String(v).replace(/[^0-9.\-]/g, ""));
  return isNaN(n) ? null : n;
}
const fmt = (v) => {
  const n = num(v);
  return n == null ? "—" : "$" + n.toLocaleString("en-US");
};

function computeCalc(p) {
  const cash = num(p.cashPrice);
  const arv = num(p.arv);
  const rehab = num(p.estRehab != null ? p.estRehab : p.rehab);
  const hasRehab = rehab != null && rehab > 0;
  const equity =
    arv != null && cash != null ? arv - cash - (hasRehab ? rehab : 0) : null;
  const allIn = cash != null ? cash + (hasRehab ? rehab : 0) : null;
  const spread =
    arv != null && cash != null ? arv - cash - (hasRehab ? rehab : 0) : null;
  const margin = equity != null && arv ? (equity / arv) * 100 : null;
  return { cash, arv, rehab, hasRehab, equity, allIn, spread, margin };
}

const isVideoUrl = (u) =>
  typeof u === "string" && /\.(mp4|mov|webm)(\?|$)/i.test(u);

/* ────────────────────────────────────────────────
   Small reusable atoms
   ──────────────────────────────────────────────── */
function StatusPill({ status }) {
  const s = status || "Available";
  const cls =
    s === "Available" ? "status-available"
    : s === "Sold" ? "status-sold"
    : "status-pending";
  return <span className={`status-pill ${cls}`}>{s}</span>;
}

function SpecRow({ label, value }) {
  return (
    <div className="spec-row">
      <div className="spec-row-label">{label}</div>
      <div className="spec-row-value num">{value}</div>
    </div>
  );
}

function SectionHead({ title, sub }) {
  return (
    <div className="section-head">
      <h2 className="h-section">{title}</h2>
      {sub && <p className="muted section-sub">{sub}</p>}
    </div>
  );
}

/* ────────────────────────────────────────────────
   Gallery (photos + videos) + lightbox
   ──────────────────────────────────────────────── */
function GalleryCombined({ media, idx, setIdx, onOpen, isSold }) {
  const stripRef = useRef(null);
  useEffect(() => {
    const strip = stripRef.current;
    if (!strip) return;
    const active = strip.children[idx];
    if (active) active.scrollIntoView({ block: "nearest", inline: "center", behavior: "smooth" });
  }, [idx]);

  if (!media.length) return null;
  const cur = media[idx];

  return (
    <div className="combo-gallery">
      <div className="combo-main" onClick={() => onOpen(idx)}>
        {cur.type === "video" ? (
          <video src={cur.url} controls playsInline onClick={(e) => e.stopPropagation()} />
        ) : (
          <img src={cur.url} alt="Property" />
        )}
        {isSold && <div className="combo-sold-flag">Sold</div>}
        <button className="hero-nav prev" onClick={(e) => { e.stopPropagation(); setIdx((idx - 1 + media.length) % media.length); }}>
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="m15 18-6-6 6-6"/></svg>
        </button>
        <button className="hero-nav next" onClick={(e) => { e.stopPropagation(); setIdx((idx + 1) % media.length); }}>
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="m9 18 6-6-6-6"/></svg>
        </button>
        <div className="hero-count">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>
          {idx + 1} / {media.length}
        </div>
      </div>
      <div className="combo-strip" ref={stripRef}>
        {media.map((m, i) => (
          <button key={i} className={`combo-thumb ${i === idx ? "is-active" : ""}`} onClick={() => setIdx(i)}>
            {m.type === "video" ? (
              <span className="combo-thumb-video">
                <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><polygon points="5,3 19,12 5,21"/></svg>
              </span>
            ) : (
              <img src={m.url} alt="" loading="lazy" />
            )}
          </button>
        ))}
      </div>
    </div>
  );
}

function Lightbox({ media, idx, setIdx, onClose }) {
  useEffect(() => {
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      if (e.key === "ArrowRight") setIdx((idx + 1) % media.length);
      if (e.key === "ArrowLeft") setIdx((idx - 1 + media.length) % media.length);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [idx, media.length]);

  const cur = media[idx];
  return (
    <div className="lightbox" onClick={onClose}>
      <button className="lb-close" onClick={onClose}>✕</button>
      <button className="lb-nav prev" onClick={(e) => { e.stopPropagation(); setIdx((idx - 1 + media.length) % media.length); }}>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="m15 18-6-6 6-6"/></svg>
      </button>
      {cur.type === "video" ? (
        <video src={cur.url} controls autoPlay playsInline onClick={(e) => e.stopPropagation()} />
      ) : (
        <img src={cur.url} onClick={(e) => e.stopPropagation()} alt="" />
      )}
      <button className="lb-nav next" onClick={(e) => { e.stopPropagation(); setIdx((idx + 1) % media.length); }}>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="m9 18 6-6-6-6"/></svg>
      </button>
      <div className="lb-count num">{idx + 1} / {media.length}</div>
    </div>
  );
}

/* ────────────────────────────────────────────────
   Property body sections
   ──────────────────────────────────────────────── */
const SPEC_ICONS = {
  type:  <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M3 12 12 4l9 8"/><path d="M5 10v10h14V10"/><path d="M10 20v-6h4v6"/></svg>,
  beds:  <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M2 16h20M2 16v4M22 16v4M4 16v-4a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v4"/><circle cx="8" cy="11" r="2"/></svg>,
  baths: <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M9 6V4a2 2 0 0 1 2-2h0a2 2 0 0 1 2 2v2"/><path d="M3 11h18M5 11v3a5 5 0 0 0 5 5h4a5 5 0 0 0 5-5v-3"/><path d="M7 21v-2M17 21v-2"/></svg>,
  sqft:  <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><rect x="3" y="3" width="18" height="18" rx="1"/><path d="M3 8h4M3 12h3M3 16h4"/></svg>,
  year:  <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M3 10h18M8 2v4M16 2v4"/></svg>,
  lot:   <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M3 21h18M5 21V8l7-5 7 5v13"/><path d="M9 21v-6h6v6"/></svg>,
};

function Specs({ p }) {
  const items = [];
  if (p.propertyType) items.push({ i: SPEC_ICONS.type, v: p.propertyType, l: "Property type" });
  if (p.bedrooms != null && p.bedrooms !== "") items.push({ i: SPEC_ICONS.beds, v: p.bedrooms, l: "Bedrooms" });
  if (p.bathrooms != null && p.bathrooms !== "") items.push({ i: SPEC_ICONS.baths, v: p.bathrooms, l: "Bathrooms" });
  if (p.sqft) items.push({ i: SPEC_ICONS.sqft, v: `${p.sqft} sqft`, l: "Livable area" });
  if (p.yearBuilt) items.push({ i: SPEC_ICONS.year, v: p.yearBuilt, l: "Year built" });
  if (p.lotSize) items.push({ i: SPEC_ICONS.lot, v: p.lotSize, l: "Lot size" });
  if (!items.length) return null;
  return (
    <div className="specs">
      {items.map((it, i) => (
        <div className="spec-cell" key={i}>
          <div className="spec-cell-icon">{it.i}</div>
          <div>
            <div className="spec-cell-value num">{it.v}</div>
            <div className="spec-cell-label">{it.l}</div>
          </div>
        </div>
      ))}
    </div>
  );
}

// Optional custom fields — supports an array [{label,value}], an object {k:v},
// or the admin CMS's flat custom1..custom7 string fields.
function CustomFields({ p }) {
  let entries = [];
  if (Array.isArray(p.customFields)) {
    entries = p.customFields
      .filter((f) => f && (f.label || f.name) && (f.value != null && f.value !== ""))
      .map((f) => [f.label || f.name, f.value]);
  } else if (p.customFields && typeof p.customFields === "object") {
    entries = Object.entries(p.customFields).filter(([, v]) => v != null && v !== "");
  } else {
    entries = [1, 2, 3, 4, 5, 6, 7]
      .map((n) => p[`custom${n}`])
      .filter((v) => v != null && v !== "")
      .map((v, i) => [null, v]);
  }
  if (!entries.length) return null;
  return (
    <div className="custom-fields">
      {entries.map(([k, v], i) => (
        <div className="custom-field" key={i}>
          {k ? <span className="custom-field-label">{k}</span> : null}
          <span className="custom-field-value">{v}</span>
        </div>
      ))}
    </div>
  );
}

function Financials({ p, c }) {
  return (
    <div className="financials">
      <div className="fin-row">
        <SpecRow label="Cash price" value={fmt(p.cashPrice)} />
        <SpecRow label="After repair value (ARV)" value={fmt(p.arv)} />
        {num(p.emd) != null && <SpecRow label="Earnest money deposit" value={fmt(p.emd)} />}
      </div>

      {c.hasRehab && (
        <>
          <hr className="rule" />
          <div className="fin-row">
            <SpecRow label="Estimated rehab" value={fmt(c.rehab)} />
            <SpecRow label="All-in cost" value={fmt(c.allIn)} />
            <SpecRow label="Spread" value={fmt(c.spread)} />
          </div>
        </>
      )}

      {c.equity != null && (
        <>
          <hr className="rule" />
          <div className="fin-row fin-row-equity">
            <div className="equity-callout">
              <div className="eyebrow">Potential Equity</div>
              <div className="equity-big num">{fmt(c.equity)}</div>
              <div className="muted">
                {c.hasRehab
                  ? "After cash purchase + estimated rehab, based on recent comparable sales."
                  : "After cash purchase, based on recent comparable sales."}
              </div>
            </div>
            {c.margin != null && (
              <div className="equity-margin">
                <div className="muted">Margin</div>
                <div className="num">{c.margin.toFixed(1)}%</div>
              </div>
            )}
          </div>
        </>
      )}
    </div>
  );
}

function MapSection({ p }) {
  const [tab, setTab] = useState("map");
  const q = encodeURIComponent(`${p.address}, ${p.city}, ${p.state} ${p.zip}`);

  // Maps Embed API key injected by the backend into window.MAPS_EMBED_KEY.
  const key = (typeof window !== "undefined" && window.MAPS_EMBED_KEY) || "";
  const hasCoords = p.lat != null && p.lng != null;
  const loc = hasCoords ? `${p.lat},${p.lng}` : q;

  // Place API accepts an address string; Street View API requires lat,lng.
  const mapSrc = key
    ? `https://www.google.com/maps/embed/v1/place?key=${key}&q=${loc}`
    : `https://www.google.com/maps?q=${q}&output=embed`;
  const streetSrc = key && hasCoords
    ? `https://www.google.com/maps/embed/v1/streetview?key=${key}&location=${loc}&fov=80`
    : `https://maps.google.com/maps?q=${q}&layer=c&output=svembed`;

  return (
    <div className="map-block">
      <div className="map-tabs">
        <button className={`map-tab ${tab === "map" ? "is-active" : ""}`} onClick={() => setTab("map")}>Map</button>
        <button className={`map-tab ${tab === "street" ? "is-active" : ""}`} onClick={() => setTab("street")}>Street view</button>
      </div>
      <div className="map-frame">
        <iframe
          key={tab}
          title={tab === "map" ? "Property location" : "Street view"}
          src={tab === "map" ? mapSrc : streetSrc}
          loading="lazy"
          allowFullScreen
        />
      </div>
      <p className="muted map-note">Street View may not be available for every block. Drag/zoom to explore the neighborhood.</p>
    </div>
  );
}

function ContactBlock() {
  return (
    <div className="contact-block">
      <div className="contact-actions">
        <a href="tel:+12408508328" className="btn btn-primary btn-lg btn-block">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
          Call now
        </a>
        <a href="sms:+12408508328" className="btn btn-ghost btn-block btn-lg">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
          Text now
        </a>
      </div>
      <div className="contact-lines">
        <div className="contact-line">
          <div className="contact-label">Phone</div>
          <a href="tel:+12408508328" className="contact-link num">(240) 850-8328</a>
        </div>
        <div className="contact-line">
          <div className="contact-label">Email</div>
          <a href="mailto:tyler@investordealvault.com" className="contact-link">tyler@investordealvault.com</a>
        </div>
      </div>
    </div>
  );
}

function VimeoSection({ urls }) {
  if (!urls || !urls.length) return null;
  return (
    <section className="block">
      <SectionHead title="Property videos" />
      <div className="vimeo-grid">
        {urls.map((url, i) => (
          <iframe
            key={i}
            src={url.replace("vimeo.com/", "player.vimeo.com/video/")}
            allow="autoplay; fullscreen; picture-in-picture"
            allowFullScreen
            title={`Property video ${i + 1}`}
          />
        ))}
      </div>
    </section>
  );
}

function AddressBlock({ p }) {
  const meta = [];
  if (p.bedrooms != null && p.bedrooms !== "") meta.push(<span key="bd"><strong className="num">{p.bedrooms}</strong> bd</span>);
  if (p.bathrooms != null && p.bathrooms !== "") meta.push(<span key="ba"><strong className="num">{p.bathrooms}</strong> ba</span>);
  if (p.sqft) meta.push(<span key="sf" className="num"><strong>{p.sqft}</strong> sqft</span>);

  return (
    <div className="address-block">
      <div className="address-crumb">
        <a href="/deals">All deals</a>
        <span>›</span>
        <span>{p.state}</span>
        <span>›</span>
        <span>{p.city}</span>
      </div>
      <h1 className="h-display address-h1">
        {p.address}, <span className="address-city">{p.city}, {p.state} {p.zip}</span>
      </h1>
      {meta.length > 0 && (
        <div className="address-meta">
          {meta.map((m, i) => (
            <React.Fragment key={i}>
              {i > 0 && <span className="dot">·</span>}
              {m}
            </React.Fragment>
          ))}
        </div>
      )}
    </div>
  );
}

function PropertyLayout({ p, c, media, idx, setIdx, onOpen }) {
  const description = p.description || p.notes || "";
  const isSold = (p.status || "") === "Sold";
  return (
    <div className="layout-A">
      <div className="lA-top">
        <AddressBlock p={p} />
        <StatusPill status={p.status} />
      </div>

      <div className="lA-gallery">
        <GalleryCombined media={media} idx={idx} setIdx={setIdx} onOpen={onOpen} isSold={isSold} />
      </div>

      <div className="lA-content">
        <VimeoSection urls={p.vimeoVideos} />

        <section className="block block-first">
          <SectionHead title="Property details" />
          <Specs p={p} />
          <CustomFields p={p} />
          {description && <p className="prose">{description}</p>}
        </section>

        {(num(p.cashPrice) != null || num(p.arv) != null) && (
          <section className="block">
            <SectionHead title="Financials" />
            <Financials p={p} c={c} />
          </section>
        )}

        <section className="block">
          <SectionHead title="Location" />
          <MapSection p={p} />
        </section>

        <section className="block lA-contact">
          <SectionHead
            title="Lock in this deal"
            sub="Call or text Tyler directly to lock in the deal — assignments are typically sent within an hour."
          />
          <ContactBlock />
        </section>
      </div>
    </div>
  );
}

/* ────────────────────────────────────────────────
   Tweaks panel
   ──────────────────────────────────────────────── */
const DEFAULT_TWEAKS = /*EDITMODE-BEGIN*/{
  "accent": "#2c7be5"
}/*EDITMODE-END*/;

function App() {
  const [tweaks, setTweak] = window.useTweaks(DEFAULT_TWEAKS);
  const [p, setP] = useState(null);
  const [phase, setPhase] = useState("loading"); // loading | ready | error
  const [idx, setIdx] = useState(0);
  const [lbOpen, setLbOpen] = useState(false);
  const [lbIdx, setLbIdx] = useState(0);

  // Apply accent live
  useEffect(() => {
    document.documentElement.style.setProperty("--brand-2", tweaks.accent);
  }, [tweaks.accent]);

  // Load the property JSON by slug (same source as the original page)
  useEffect(() => {
    const slug = getSlug();
    if (!slug) { setPhase("error"); return; }
    let cancelled = false;
    (async () => {
      try {
        const r = await fetch(`/api/get-property?slug=${encodeURIComponent(slug)}`);
        if (!r.ok) { if (!cancelled) setPhase("error"); return; }
        const data = await r.json();
        if (cancelled) return;
        setP(data);
        setPhase("ready");
        if (data.address) {
          document.title = `${data.address}, ${data.city}, ${data.state} ${data.zip} - InvestorDealVault`;
        }
      } catch (e) {
        if (!cancelled) setPhase("error");
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const media = useMemo(() => {
    if (!p) return [];
    const imgs = (p.photos || []).filter(Boolean).map((u) => ({ type: "image", url: u }));
    const vids = (p.videos || []).filter(Boolean).map((u) => ({ type: "video", url: u }));
    // Some feeds put mp4s in the photos array — classify by extension just in case.
    return [...imgs, ...vids].map((m) =>
      m.type === "image" && isVideoUrl(m.url) ? { type: "video", url: m.url } : m
    );
  }, [p]);

  const c = useMemo(() => (p ? computeCalc(p) : null), [p]);

  const openLb = (i) => { setLbIdx(i); setLbOpen(true); };

  const Tweaks = window.TweaksPanel;
  const { TweakSection, TweakColor } = window;

  let body;
  if (phase === "loading") {
    body = <div className="property-state">Loading property…</div>;
  } else if (phase === "error" || !p) {
    body = (
      <div className="property-state">
        <h1>Property not found</h1>
        <p className="muted">This listing may have been removed.</p>
        <a href="/deals" className="btn btn-primary" style={{ marginTop: "8px" }}>Back to all deals</a>
      </div>
    );
  } else {
    body = (
      <>
        <PropertyLayout p={p} c={c} media={media} idx={idx} setIdx={setIdx} onOpen={openLb} />
        {lbOpen && (
          <Lightbox media={media} idx={lbIdx} setIdx={setLbIdx} onClose={() => setLbOpen(false)} />
        )}
      </>
    );
  }

  return (
    <>
      {body}
      <Tweaks title="Tweaks">
        <TweakSection label="Brand accent" />
        <TweakColor
          label="Accent"
          value={tweaks.accent}
          onChange={(v) => setTweak("accent", v)}
          options={["#2c7be5", "#1e3a8a", "#0ea5e9", "#0c1f4a"]}
        />
      </Tweaks>
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
