// Admin Inbox — live view of submitted /quotes briefs.
//
// Reads with onSnapshot so a quote arriving in the client portal appears
// here within a second. Status changes write straight back to Firestore
// and append a row to /audit. Briefs are rendered as collapsible
// key/value lists since each service has its own shape — kept generic
// so we don't have to special-case every flow's review schema.

const SERVICE_LABELS = {
  "promotional-videos":        "Promotional Videos",
  "real-estate-commercial":    "Commercial Real Estate",
  "fpv-fly-throughs":          "FPV Fly-Throughs",
  "construction":              "Construction Documentation",
  "property-documentation":    "Property Documentation",
  "tourism":                   "Tourism & Community",
  "events":                    "Event Coverage",
  "social-media":              "Social Media Retainer",
};

const STATUS_FLOW = [
  { id: "new",         label: "New" },
  { id: "in-progress", label: "In progress" },
  { id: "quoted",      label: "Quoted" },
  { id: "won",         label: "Won" },
  { id: "lost",        label: "Lost" },
  { id: "archived",    label: "Archived" },
];

const statusLabel = (s) => (STATUS_FLOW.find(x => x.id === s) || { label: s }).label;

const formatTimestamp = (ts) => {
  if (!ts) return "—";
  const d = ts.toDate ? ts.toDate() : new Date(ts);
  return d.toLocaleString("en-US", {
    month: "short", day: "numeric", year: "numeric",
    hour: "numeric", minute: "2-digit",
  });
};

const briefSnippet = (brief) => {
  // Hunt for the first useful free-text-y field to show on the row.
  const candidates = [
    brief.about, brief.goal, brief.spaceDescription, brief.projectDescription,
    brief.aboutLand, brief.coverageDetail, brief.moments, brief.notes,
  ];
  const hit = candidates.find(v => typeof v === "string" && v.trim().length > 0);
  if (!hit) return "";
  return hit.length > 140 ? hit.slice(0, 137) + "…" : hit;
};

// ── Inbox module ──────────────────────────────────────────────

const AdminInboxModule = ({ user }) => {
  const [quotes, setQuotes] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [filter, setFilter] = React.useState("active"); // active | all | <statusId>
  const [openId, setOpenId] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    const fb = window.fb;
    if (!fb) return;

    const q = fb.query(
      fb.collection(fb.db, "quotes"),
      fb.orderBy("createdAt", "desc"),
      fb.limit(200)
    );

    const unsub = fb.onSnapshot(
      q,
      (snap) => {
        if (cancelled) return;
        const list = [];
        snap.forEach((d) => list.push({ id: d.id, ...d.data() }));
        setQuotes(list);
        setLoading(false);
      },
      (err) => {
        if (cancelled) return;
        console.error("inbox subscribe failed:", err);
        setError(err.message || "Couldn't load inbox.");
        setLoading(false);
      }
    );

    return () => { cancelled = true; unsub && unsub(); };
  }, []);

  const filtered = React.useMemo(() => {
    if (filter === "all") return quotes;
    if (filter === "active") {
      return quotes.filter(q => q.status !== "won" && q.status !== "lost" && q.status !== "archived");
    }
    return quotes.filter(q => q.status === filter);
  }, [quotes, filter]);

  const updateStatus = async (quote, nextStatus) => {
    const fb = window.fb;
    try {
      await fb.updateDoc(
        fb.doc(fb.db, "quotes", quote.id),
        { status: nextStatus, statusChangedAt: fb.serverTimestamp() }
      );
      // Audit log — append-only per rules.
      await fb.addDoc(fb.collection(fb.db, "audit"), {
        action: "quote.status",
        adminUid: user.uid,
        targetType: "quote",
        targetId: quote.id,
        from: quote.status || null,
        to: nextStatus,
        at: fb.serverTimestamp(),
      });
    } catch (err) {
      alert("Couldn't update status: " + (err.message || err));
    }
  };

  const deleteQuote = async (quote) => {
    if (!confirm(`Delete this quote from ${quote.submitterEmail || quote.submitterName || "unknown"}? This can't be undone.`)) return;
    const fb = window.fb;
    try {
      await fb.deleteDoc(fb.doc(fb.db, "quotes", quote.id));
      await fb.addDoc(fb.collection(fb.db, "audit"), {
        action: "quote.delete",
        adminUid: user.uid,
        targetType: "quote",
        targetId: quote.id,
        snapshot: {
          service: quote.service,
          status: quote.status,
          submitterEmail: quote.submitterEmail || null,
        },
        at: fb.serverTimestamp(),
      });
    } catch (err) {
      alert("Couldn't delete: " + (err.message || err));
    }
  };

  const counts = React.useMemo(() => {
    const c = { all: quotes.length, active: 0 };
    STATUS_FLOW.forEach(s => { c[s.id] = 0; });
    quotes.forEach(q => {
      if (c[q.status] != null) c[q.status]++;
      if (q.status !== "won" && q.status !== "lost" && q.status !== "archived") c.active++;
    });
    return c;
  }, [quotes]);

  if (loading) {
    return <div className="admin-placeholder"><p>Loading inbox…</p></div>;
  }
  if (error) {
    return <div className="admin-placeholder"><h2>Couldn't load</h2><p>{error}</p></div>;
  }

  return (
    <div>
      <div className="inbox-filters">
        <button className={`inbox-filter ${filter === "active" ? "active" : ""}`} onClick={() => setFilter("active")}>
          Active <span className="inbox-filter-count">{counts.active}</span>
        </button>
        {STATUS_FLOW.map(s => (
          <button
            key={s.id}
            className={`inbox-filter ${filter === s.id ? "active" : ""}`}
            onClick={() => setFilter(s.id)}
          >
            {s.label} <span className="inbox-filter-count">{counts[s.id] || 0}</span>
          </button>
        ))}
        <button className={`inbox-filter ${filter === "all" ? "active" : ""}`} onClick={() => setFilter("all")}>
          All <span className="inbox-filter-count">{counts.all}</span>
        </button>
      </div>

      {filtered.length === 0 ? (
        <div className="admin-placeholder">
          <span className="eyebrow">NOTHING TO SHOW</span>
          <h2>{filter === "active" ? "No active quotes" : "No quotes match this filter"}</h2>
          <p>When a client submits a brief, it'll land here in real time.</p>
        </div>
      ) : (
        <div className="inbox-list">
          {filtered.map(q => (
            <InboxRow
              key={q.id}
              quote={q}
              isOpen={openId === q.id}
              onToggle={() => setOpenId(openId === q.id ? null : q.id)}
              onStatusChange={(next) => updateStatus(q, next)}
              onDelete={() => deleteQuote(q)}
            />
          ))}
        </div>
      )}
    </div>
  );
};

// ── One row + expanded view ───────────────────────────────────

const InboxRow = ({ quote, isOpen, onToggle, onStatusChange, onDelete }) => {
  const serviceLabel = SERVICE_LABELS[quote.service] || quote.service || "Unknown service";
  const snippet = briefSnippet(quote.brief || {});

  return (
    <div className={`inbox-row ${isOpen ? "open" : ""}`}>
      <button className="inbox-row-head" onClick={onToggle}>
        <span className={`inbox-status status-${quote.status || "new"}`}>{statusLabel(quote.status)}</span>
        <div className="inbox-row-main">
          <div className="inbox-row-title">
            <strong>{quote.submitterName || "Unknown sender"}</strong>
            <span className="inbox-row-svc">{serviceLabel}</span>
          </div>
          {snippet && <div className="inbox-row-snippet">{snippet}</div>}
        </div>
        <div className="inbox-row-meta">
          <div>{formatTimestamp(quote.createdAt)}</div>
          {quote.submitterEmail && <div className="inbox-row-email">{quote.submitterEmail}</div>}
        </div>
      </button>

      {isOpen && (
        <div className="inbox-row-body">
          <div className="inbox-actions">
            <label>
              <span className="eyebrow">STATUS</span>
              <select
                className="select"
                value={quote.status || "new"}
                onChange={(e) => onStatusChange(e.target.value)}
              >
                {STATUS_FLOW.map(s => <option key={s.id} value={s.id}>{s.label}</option>)}
              </select>
            </label>
            {quote.submitterEmail && (
              <a className="btn ghost" href={`mailto:${quote.submitterEmail}?subject=Re: your ${serviceLabel} brief`}>
                Reply by email
              </a>
            )}
            <button className="btn ghost danger" onClick={onDelete}>
              Delete
            </button>
          </div>

          <div className="inbox-brief">
            <BriefView brief={quote.brief || {}} />
          </div>

          <div className="inbox-foot">
            <span>Quote ID: <code>{quote.id}</code></span>
            {quote.submitterUid && <span>Submitter UID: <code>{quote.submitterUid}</code></span>}
          </div>
        </div>
      )}
    </div>
  );
};

// ── Generic brief renderer ────────────────────────────────────
// Each service's brief is a flat object of mixed types. We render it as
// a key/value table, hiding empty values to keep the view useful.

const FIELD_LABELS = {
  contactName: "Contact name",
  company: "Company",
  brokerage: "Brokerage",
  orgName: "Organization",
  email: "Email",
  phone: "Phone",
  website: "Website",
  handles: "Social handles",
  address: "Address",
  secondaryAddress: "Secondary address",
  location: "Location",
  eventName: "Event name",
  about: "About",
  audience: "Audience",
  goal: "Goal",
  goalDetail: "Success looks like",
  offering: "What they do",
  spaceDescription: "About the space",
  buildingType: "Building type",
  propertyKind: "Property type",
  occupancy: "Occupancy",
  sqft: "Square footage",
  floors: "Floors",
  beds: "Beds",
  units: "Buildings / units",
  features: "Features",
  featuresOther: "Other features",
  customBrief: "Description",
  useCases: "Use cases",
  budget: "Budget",
  targetDate: "Target date",
  deadline: "Deadline",
  notes: "Notes",
  cadence: "Cadence",
  constructionType: "Construction type",
  projectDescription: "Project description",
  projectDuration: "Project duration",
  services: "Services",
  frequency: "Frequency",
  startDate: "Start date",
  endDate: "End date",
  shootDates: "Shoot dates",
  numVisits: "Number of visits",
  goals: "Goals",
  goalsOther: "Other goals",
  landType: "Land type",
  acreage: "Acreage",
  aboutLand: "About the land",
  focusAreas: "Focus areas",
  season: "Season",
  orgType: "Org type",
  audiences: "Audiences",
  coverage: "Coverage",
  coverageDetail: "Specifics",
  placements: "Placements",
  placementsOther: "Other placements",
  eventType: "Event type",
  expectedAttendance: "Expected attendance",
  venueType: "Venue type",
  eventDates: "Event dates",
  timeOfDay: "Time of day",
  moments: "Key moments",
  turnaround: "Turnaround",
  success: "Success looks like",
  scope: "Scope",
  visitsPerMonth: "Visits / mo",
  piecesPerMonth: "Pieces / mo",
  contentMix: "Content mix",
  channels: "Channels",
  tier: "Tier",
};

const labelize = (key) => FIELD_LABELS[key] || key.replace(/([A-Z])/g, " $1").replace(/^./, c => c.toUpperCase());

const formatValue = (v) => {
  if (v == null || v === "") return null;
  if (Array.isArray(v)) return v.length ? v.join(", ") : null;
  if (typeof v === "object") return JSON.stringify(v);
  return String(v);
};

const BriefView = ({ brief }) => {
  const entries = Object.entries(brief)
    .map(([k, v]) => [k, formatValue(v)])
    .filter(([, v]) => v !== null);

  if (entries.length === 0) {
    return <div className="inbox-brief-empty">No fields submitted.</div>;
  }

  return (
    <div className="inbox-brief-grid">
      {entries.map(([k, v]) => (
        <div key={k} className="inbox-brief-row">
          <span className="inbox-brief-label">{labelize(k)}</span>
          <span className="inbox-brief-value">{v}</span>
        </div>
      ))}
    </div>
  );
};

window.AdminInboxModule = AdminInboxModule;
