/* global window */
// Room builder — turns a Nudge deal into a config for the shareable prospect
// room (room/index.html) and encodes it into a self-contained share link.
// Everything the prospect sees is derived from the live deal: the recap, the
// agenda, and the two generated one-pager documents (rendered by doc.html).
// No backend — the whole room rides in the link as a base64url blob.
//
// Exposes:
//   window.ROOM_ENABLED_DEALS            -> ids with rooms enabled (data-limited)
//   window.canShareRoom(deal)            -> bool
//   window.buildRoomConfig(deal,{blank}) -> config object
//   window.draftRoomIntro(deal)          -> intro string (deal-driven)
//   window.draftRoomAgenda(deal)         -> array of agenda strings
//   window.buildRoomDocs(deal)           -> array of generated document configs
//   window.encodeRoomLink(config)        -> absolute share URL

(function () {
  // Rooms are enabled on a curated set of data-rich deals only — one per
  // rhythm verdict (off-beat / on-beat / lost-beat) — to keep the demo tight.
  const ROOM_ENABLED = ["atlas", "acme", "techstart"];
  window.ROOM_ENABLED_DEALS = ROOM_ENABLED.slice();
  window.canShareRoom = (deal) => !!deal && ROOM_ENABLED.indexOf(deal.id) > -1;

  // The seller persona for the prototype (mirrors the standalone pod). Real
  // wiring would read this from the signed-in user / settings.
  const SELLER = {
    name: "Ridha Mami",
    initials: "RM",
    title: "Founder · Addvocate",
    email: "ridha@addvocate.ai",
    phone: "+33 7 64 45 40 24",
    slack: {
      label: "Slack · connect with me",
      value: "@ridha · Addvocate",
      href: "https://join.slack.com/t/addvocateworkspace/shared_invite/zt-428dkn27n-RP5XbsrM1W5Kn_UiweKzvQ",
    },
  };

  const firstName = (full) => String(full || "").trim().split(/\s+/)[0] || "there";

  // ---- Client brand: logo mark + palette, per room ----------------------
  // Curated palettes for the room-enabled deals; any other company gets a
  // stable palette derived from its name (hash → hue), so every room still
  // arrives branded. The room page maps these onto its CSS variables.
  const BRANDS = {
    atlas: { primary: "#B45309", deep: "#92400E", light: "#F59E0B", tint: "#FDF3E7" },
    acme: { primary: "#B91C1C", deep: "#991B1B", light: "#EF4444", tint: "#FDEEEE" },
    techstart: { primary: "#0F766E", deep: "#115E59", light: "#2DD4BF", tint: "#EAF9F6" },
  };

  const initialsOf = (name) =>
    String(name || "")
      .split(/\s+/)
      .filter(Boolean)
      .slice(0, 2)
      .map((w) => w[0].toUpperCase())
      .join("") || "•";

  function hashHue(str) {
    let h = 0;
    for (let i = 0; i < str.length; i++) h = (h * 31 + str.charCodeAt(i)) % 360;
    return h;
  }

  function brandFor(deal) {
    const preset = BRANDS[deal.id];
    const name = deal.company || "Your company";
    if (preset) return { name, initials: initialsOf(name), ...preset };
    const hue = hashHue(name);
    return {
      name,
      initials: initialsOf(name),
      primary: `hsl(${hue}, 55%, 38%)`,
      deep: `hsl(${hue}, 60%, 30%)`,
      light: `hsl(${hue}, 60%, 55%)`,
      tint: `hsl(${hue}, 45%, 96%)`,
    };
  }

  // ---- In-room assistant: buyer-safe knowledge pack ----------------------
  // Everything the room's AI concierge may draw on, from the BUYER's side of
  // the table: the shared state of the deal, what the product does, and who
  // the company is. No scores, no Addy notes, no competitive intel — the same
  // strip rule the rest of the room follows. Rides in the share link, powers
  // both the live Claude endpoint (api/room-agent.js) and the offline
  // keyword concierge fallback.
  const PRODUCT_FACTS = [
    "Nudge is a buyer-proof layer for B2B deals: it runs a weekly read on whether each deal shows real buyer movement, so both sides always know where things actually stand.",
    "It reads signals from the channels work already happens in (email, calendar, Slack, WhatsApp, LinkedIn) — read-only, zero data entry. Nobody on either side fills in a CRM.",
    "Rooms like this one are part of the product: one shared, private page per deal — the recap, the documents, the agenda — instead of attachments and forwarded threads.",
    "Implementation is light: connect email + calendar (about 15 minutes), invite the team, and the first weekly read arrives within days. A typical pilot runs 2 weeks.",
    "Security: data is encrypted in transit and at rest, access is per-deal and per-person, and customer data is never used to train models. EU or US hosting available.",
    "Pricing is per revenue seat, billed annually, tiered by team size. The number in this room reflects the proposal on the table — the final shape is agreed together before signature.",
    "After signing: a dedicated onboarding contact, a shared Slack channel with the founding team, and a 30-day check against the success criteria agreed in the plan.",
  ].join("\n");

  const COMPANY_FACTS = [
    "Addvocate is the company behind Nudge — founder-led, built by people who carried a quota and got tired of forecast theatre.",
    `${SELLER.name} (${SELLER.title}) is your contact on this deal — reachable by Slack, email (${SELLER.email}) or phone, whatever is lightest.`,
    "The team works out of Paris and London and builds in close partnership with its first customers — feedback from rooms like this one shapes the roadmap directly.",
  ].join("\n");

  function buildAssistantPack(deal) {
    const next = nextMeeting(deal);
    const last = lastPastMeeting(deal);
    const people = (deal.stakeholders || [])
      .filter((s) => !s.missing)
      .map((s) => `${s.name} (${s.role})`);
    return {
      prospect: firstName(deal.champion),
      company: deal.company,
      seller: SELLER.name,
      seller_first: firstName(SELLER.name),
      deal: {
        name: deal.dealName || "",
        stage: deal.stage,
        value: fmtValue(deal),
        close_date: deal.closeDate || "",
        last_meeting: last ? `${last.title} on ${dateOnly(last.date)}` : "",
        // Title + date only — meeting `goal` is seller-side prep and stays out.
        next_meeting: next ? `${next.title} on ${dateOnly(next.date)}` : "",
        people,
        agenda: draftRoomAgenda(deal),
        focus: primaryTheme(deal).topic,
      },
      product: PRODUCT_FACTS,
      about: COMPANY_FACTS,
      suggested: [
        "Where are we in this deal, exactly?",
        "What does Nudge actually do, in plain terms?",
        "How do you handle our data and security?",
        "How does pricing work?",
        "What happens after we sign?",
      ],
    };
  }

  const fmtValue = (deal) => {
    if (deal.arr) return String(deal.arr).replace(/\s*ARR\s*$/i, "");
    const v = Number(deal.value || 0);
    if (!v) return "";
    return v >= 1000 ? `$${Math.round(v / 1000)}K` : `$${v}`;
  };

  // "Apr 30, 3:00 PM PT" -> "Apr 30"; "May 20, 2026" -> "May 20, 2026"
  const dateOnly = (s) =>
    String(s || "").replace(/\s*\d{1,2}:\d{2}[^,]*$/i, "").replace(/,\s*$/, "").trim();

  const rhythmOf = (deal) =>
    typeof window.getDealRhythm === "function" ? window.getDealRhythm(deal) : null;

  const pastMeetings = (deal) => (deal.meetings || []).filter((m) => m.isPast);
  const nextMeeting = (deal) => (deal.meetings || []).find((m) => !m.isPast) || null;
  const lastPastMeeting = (deal) => pastMeetings(deal)[0] || null;

  // Strip seller-internal signals so nothing the prospect shouldn't see leaks
  // into the room (scores, Addy notes, competitor/battlecard mentions, etc.).
  const BANNED = /\bscore|addy|battlecard|linnworks|competitor|displacement|went silent|stall|\bpts\b|engagement dropped|silent blocker/i;
  const firstSentence = (text) => String(text || "").split(/(?<=\.)\s+/)[0] || "";
  function safeSentence(text) {
    const s = firstSentence(text);
    return BANNED.test(s) ? "" : s.trim();
  }
  // Re-frame a seller next-step into a mutual, buyer-facing line.
  function cleanStep(s) {
    s = String(s || "").trim();
    if (!s || BANNED.test(s)) return null;
    s = s
      .replace(/^push for (the )?/i, "Line up ")
      .replace(/^send /i, "Share ")
      .replace(/^schedule /i, "Set up ")
      .replace(/^confirm /i, "Confirm ")
      .replace(/\s+to [A-Z][a-z]+ [A-Z][a-z]+\b/, ""); // drop "to Aiden Park"
    return s.charAt(0).toUpperCase() + s.slice(1);
  }

  // What the deal's live signals mean, translated for the buyer.
  function themeForKind(kind) {
    const k = String(kind || "").toUpperCase();
    if (/BLOCK/.test(k)) return { topic: "clearing the last open item before we sign", line: "Clear the final blocker so the timeline holds." };
    if (/COMPET|GAP/.test(k)) return { topic: "making sure we're the right fit as you weigh the options", line: "Talk through where we fit best vs. the alternatives." };
    if (/STAKEHOLDER|DECISION/.test(k)) return { topic: "getting the right people in the room", line: "Agree who else needs to weigh in before we go further." };
    if (/APPROVAL|PROCESS/.test(k)) return { topic: "mapping the steps to a signature", line: "Map the steps and owners on the path to sign-off." };
    if (/OPPORTUN/.test(k)) return { topic: "lining up the final commit", line: "Confirm the close date and the redline window." };
    return { topic: "keeping our momentum", line: "Confirm next steps and timing." };
  }
  const primaryTheme = (deal) =>
    themeForKind((deal.nudges && deal.nudges[0] && deal.nudges[0].kind) || "");

  // ---- Deal-driven intro: rhythm-aware, grounded in the deal's own fields ----
  function draftRoomIntro(deal) {
    const name = firstName(deal.champion);
    const val = fmtValue(deal);
    const rhythm = rhythmOf(deal);
    const last = lastPastMeeting(deal);
    const lastRef = last ? `the ${last.title.toLowerCase()}` : "we last spoke";
    const theme = primaryTheme(deal);

    const opener =
      rhythm === "lost-beat"
        ? `${name} — I know things slowed on our side since ${lastRef}, and I didn't want that to be where we leave it.`
        : rhythm === "on-beat"
        ? `${name} — we've had real momentum since ${lastRef}, so I want to keep our next conversation sharp.`
        : `${name} — it's been a few days since ${lastRef}, so I pulled together where we are before we pick it back up.`;

    const mid = `Think of this as a shared room for <b>${deal.company}</b>${
      val ? ` · ${val}` : ""
    }: a quick recap of where we've got to, the documents that matter, and the few things worth your read on ${theme.topic}${
      deal.closeDate ? ` before ${deal.closeDate}` : ""
    }.`;

    return `${opener} ${mid} <b>Tick what matters, edit any line, add what you want to cover</b> — it'll be here when we talk.`;
  }

  // ---- "Where we are": neutral, factual read of the deal's current state ----
  function draftRoomContent(deal) {
    const val = fmtValue(deal);
    const last = lastPastMeeting(deal);
    const next = nextMeeting(deal);
    const theme = primaryTheme(deal);
    const bits = [];
    bits.push(
      `We're at the <strong>${deal.stage}</strong> stage on ${
        deal.dealName ? `<strong>${deal.dealName}</strong>` : "this"
      }${val ? `, a ${val} commitment` : ""}.`
    );
    if (last) {
      bits.push(
        `We last met for the <strong>${last.title}</strong> on ${dateOnly(last.date)}${
          next ? `, and we've got the ${next.title} lined up for ${dateOnly(next.date)}` : ""
        }.`
      );
    }
    bits.push(`The one thing I'd most like to get right with you now is ${theme.topic}. <strong>If anything here looks off, change it — this room is yours as much as mine.</strong>`);
    return bits.join(" ");
  }

  // ---- Agenda: one buyer-facing line per live signal, then the outcome ----
  function draftRoomAgenda(deal) {
    const lines = [];
    (deal.nudges || []).forEach((n) => lines.push(themeForKind(n.kind).line));
    lines.push(
      `The one outcome that would make ${deal.closeDate ? `the ${deal.closeDate} close` : "this"} an obvious yes for you.`
    );
    const seen = {};
    const out = [];
    lines.forEach((l) => {
      const k = l.toLowerCase();
      if (!seen[k]) { seen[k] = 1; out.push(l); }
    });
    return out.slice(0, 4);
  }

  // ---- Generated documents — one-pagers built from the deal's own story ----
  // Each returns a { title, meta, desc, doc } where `doc` is the payload that
  // doc.html renders (and which room/index.html encodes into the doc link).
  function buildRoomDocs(deal) {
    const val = fmtValue(deal);
    const past = pastMeetings(deal);
    const next = nextMeeting(deal);
    const last = lastPastMeeting(deal);
    const theme = primaryTheme(deal);

    const header = {
      brandInitials: SELLER.initials,
      company: deal.company,
      dealName: deal.dealName || "",
      value: val,
      closeDate: deal.closeDate || "",
      prospect: deal.champion || "",
      seller: SELLER.name,
    };

    // Doc 1 — "Where we are": the journey so far + current focus.
    const milestones = past
      .slice()
      .reverse()
      .map((m) => ({
        date: dateOnly(m.date),
        title: m.title,
        note: (m.debrief && safeSentence(m.debrief.summary)) || m.goal || "",
      }));
    const recap = {
      ...header,
      kind: "where-we-are",
      title: `Where we are · ${deal.company}`,
      subtitle: `A shared recap${deal.dealName ? " — " + deal.dealName : ""}, prepared for ${firstName(deal.champion)}.`,
      blocks: [
        { type: "callout", label: "Stage", value: deal.stage, sub: [val, deal.closeDate ? `target close ${deal.closeDate}` : ""].filter(Boolean).join(" · ") },
        milestones.length
          ? { type: "timeline", heading: "The story so far", items: milestones }
          : null,
        { type: "para", heading: "Where we are now", text: `The piece that matters most right now is ${theme.topic}${next ? `, which is exactly what I'd like to use our ${dateOnly(next.date)} time for` : ""}.` },
      ].filter(Boolean),
      footer: `Shared privately with ${deal.champion || "you"} · ${SELLER.name}`,
    };

    // Doc 2 — "Mutual action plan": the proposed path to close.
    const steps = [];
    if (last && last.debrief && Array.isArray(last.debrief.nextSteps)) {
      last.debrief.nextSteps.forEach((s) => {
        const c = cleanStep(s);
        if (c) steps.push({ step: c });
      });
    }
    if (next) steps.push({ step: next.title, when: dateOnly(next.date) });
    if (!steps.length) steps.push({ step: theme.line });

    const people = (deal.stakeholders || [])
      .filter((s) => !s.missing)
      .map((s) => ({ name: s.name, role: s.role }));
    const missing = (deal.stakeholders || []).find((s) => s.missing && (s.power || 0) >= 4);
    const missingNote = missing
      ? `Still to involve: ${missing.role}${missing.name ? ` (${missing.name})` : ""} — worth a quick intro before we go further.`
      : "";

    const plan = {
      ...header,
      kind: "action-plan",
      title: `Mutual action plan · path to ${deal.closeDate || "close"}`,
      subtitle: `What we've each got, on the way to ${deal.closeDate ? deal.closeDate : "a decision"}.`,
      blocks: [
        { type: "callout", label: "Target close", value: deal.closeDate || "TBD", sub: [val, deal.dealName].filter(Boolean).join(" · ") },
        { type: "list", heading: "Plan to close", items: steps.map((s) => (s.when ? `${s.step} — by ${s.when}` : s.step)) },
        people.length ? { type: "people", heading: "Who's involved", items: people } : null,
        missingNote ? { type: "para", heading: "One gap to close", text: missingNote } : null,
      ].filter(Boolean),
      footer: `Shared privately with ${deal.champion || "you"} · ${SELLER.name}`,
    };

    return [
      { title: recap.title, meta: "1-page recap", desc: "Where we've got to and what matters most right now.", doc: recap },
      { title: plan.title, meta: "1-page plan", desc: `The proposed path to ${deal.closeDate || "close"} — steps and the people involved.`, doc: plan },
    ];
  }

  // ---- Full config from a deal (or a blank-intro variant for "do it myself") ----
  function buildRoomConfig(deal, opts) {
    opts = opts || {};
    const val = fmtValue(deal);
    const name = firstName(deal.champion);
    const next = nextMeeting(deal);

    return {
      v: 1,
      id: deal.id || "deal",
      company: deal.company || "",
      prospect: deal.champion || "",
      prospectRole: deal.championRole || "",
      dealName: deal.dealName || "",
      value: val,
      closeDate: deal.closeDate || "",
      seller: SELLER.name,
      sellerInitials: SELLER.initials,
      sellerTitle: SELLER.title,
      brand: brandFor(deal),
      assistant: buildAssistantPack(deal),
      heroTitle: "So we can make the time count.",
      intro: opts.blank ? "" : draftRoomIntro(deal),
      contentLabel: "Where we are",
      contentBody: opts.blank ? "" : draftRoomContent(deal),
      video: {
        src: "nudge-demo.mp4",
        poster: "nudge-demo-poster.jpg",
        kicker: "47-second demo",
        title: "The thesis, live",
        blurb: `A quick look at how we'd run ${deal.dealName || "this"} — verified motion, the next move surfaced, nothing slipping between meetings.`,
      },
      docs: opts.blank ? [] : buildRoomDocs(deal),
      agenda: opts.blank
        ? ["Where things stand today, and what good looks like to you."]
        : draftRoomAgenda(deal),
      reach: { slack: SELLER.slack, email: SELLER.email, phone: SELLER.phone },
      cta: {
        label: next ? `Lock the ${dateOnly(next.date)} ${next.title.toLowerCase()}` : `Talk soon, ${name}`,
        href: `mailto:${SELLER.email}?subject=${encodeURIComponent(
          (deal.company ? deal.company + " · " : "") + (next ? next.title : "talk soon")
        )}`,
      },
      egg: {
        title: "You found the hidden track.",
        body:
          "Most sellers stop at “best regards” and a slide deck nobody opens. This is the opposite of that — everything useful, up front, so the live time can be a real conversation. Talk soon.",
      },
    };
  }

  function b64url(str) {
    return btoa(unescape(encodeURIComponent(str)))
      .replace(/\+/g, "-")
      .replace(/\//g, "_")
      .replace(/=+$/, "");
  }

  function encodeRoomLink(config) {
    const origin = (window.location && window.location.origin) || "";
    return `${origin}/room/#${b64url(JSON.stringify(config))}`;
  }

  window.buildRoomConfig = buildRoomConfig;
  window.draftRoomIntro = draftRoomIntro;
  window.draftRoomContent = draftRoomContent;
  window.draftRoomAgenda = draftRoomAgenda;
  window.buildRoomDocs = buildRoomDocs;
  window.encodeRoomLink = encodeRoomLink;
})();
