/* Diagnostic + brief generators. Pure functions of intake. */

const COMP_BENCH = {
  CFO:        { startup:[180,260], growth:[250,350], "mid-market":[300,450], enterprise:[450,700], turnaround:[300,500] },
  "VP Sales": { startup:[180,260], growth:[220,320], "mid-market":[260,380], enterprise:[350,550], turnaround:[260,400] },
  Product:    { startup:[180,260], growth:[220,320], "mid-market":[260,380], enterprise:[350,550], turnaround:[260,400] },
  Engineering:{ startup:[200,280], growth:[260,360], "mid-market":[300,420], enterprise:[400,600], turnaround:[280,420] },
  Ops:        { startup:[160,240], growth:[220,310], "mid-market":[260,380], enterprise:[350,520], turnaround:[260,400] },
  Other:      { startup:[160,240], growth:[220,310], "mid-market":[260,380], enterprise:[350,520], turnaround:[260,400] },
};

const HUB_CITIES = [
  "new york","nyc","san francisco","sf","los angeles","la","boston","chicago",
  "austin","seattle","denver","washington","dc","miami","atlanta","london","toronto",
];

const FUNCTION_KEYWORDS = {
  finance: ["fp&a","accounting","controller","treasury","audit","close process","gaap","sec reporting","tax","cfo","erp"],
  sales: ["quota","pipeline","ote","sales","revenue ops","channel","closing","enterprise sales","smb sales"],
  marketing: ["demand gen","brand","growth marketing","seo","content marketing","marketing ops"],
  product: ["prd","roadmap","backlog","product strategy","user research","product-led"],
  engineering: ["kubernetes","distributed systems","platform engineering","sre","staff engineer","architect"],
  ops: ["supply chain","logistics","operations","manufacturing","procurement","six sigma"],
  legal: ["general counsel","contracts","m&a","compliance","regulatory"],
  people: ["talent","recruiting","people ops","chro","hrbp"],
};

function detectFunctions(text) {
  const t = (text || "").toLowerCase();
  const hits = {};
  for (const [k, kws] of Object.entries(FUNCTION_KEYWORDS)) {
    let count = 0;
    for (const kw of kws) if (t.includes(kw)) count++;
    if (count) hits[k] = count;
  }
  return hits;
}

function runDiagnostic(i) {
  const gates = [];

  // Gate 1: Comp band
  const bench = (COMP_BENCH[i.role_family] || COMP_BENCH.Other)[i.stage] || [200, 300];
  let g1 = { yes: true, reason: "", intervention: "" };
  if (i.cash_high) {
    if (i.cash_high < bench[0] * 1000) {
      g1.yes = false;
      g1.reason = `Cash ceiling $${(i.cash_high/1000).toFixed(0)}K vs. directional market for ${i.role_family} @ ${i.stage}: $${bench[0]}K–$${bench[1]}K. Below market.`;
      g1.intervention = "Pre-kickoff client conversation: comp gap, sign-on flex, or equity authority.";
    } else {
      g1.reason = `Cash band $${(i.cash_low/1000).toFixed(0)}–${(i.cash_high/1000).toFixed(0)}K intersects directional market ($${bench[0]}–${bench[1]}K). Validate against live comp data in calibration calls.`;
    }
  } else {
    g1.yes = false;
    g1.reason = "Cash band not provided.";
    g1.intervention = "Get cash band before kickoff. Required input.";
  }
  gates.push({ q: "Does the comp band match the actual market clearing price for this profile?", short: "Comp band", ...g1 });

  // Gate 2: Composite role
  const blob = (i.must_haves.join(" ") + " " + i.role_title + " " + i.mandate).toLowerCase();
  const hits = detectFunctions(blob);
  const strongSecond = Object.entries(hits).filter(([_, c]) => c >= 2).length;
  let g2 = { yes: true, reason: `Detected functional language: ${Object.keys(hits).join(", ") || "none"}.`, intervention: "" };
  if (strongSecond >= 2) {
    g2.yes = false;
    g2.reason = `Must-haves span ${strongSecond} functions with strong signal (${Object.entries(hits).filter(([_,c])=>c>=2).map(([k,c])=>`${k}:${c}`).join(", ")}). Likely composite role.`;
    g2.intervention = `Force the "if you had to choose one" conversation with HM. Cut scope.`;
  }
  gates.push({ q: "Is the must-haves list one role, or two roles in a trench coat?", short: "Scope coherence", ...g2 });

  // Gate 3: Geo
  let g3 = { yes: true, reason: "", intervention: "" };
  const geoLow = (i.geography || "").toLowerCase();
  const isHub = HUB_CITIES.some(h => geoLow.includes(h));
  if (i.remote_policy === "onsite" && i.geography && !isHub) {
    g3.yes = false;
    g3.reason = `Onsite required in ${i.geography} (non-hub). Talent pool for ${i.role_family} thins materially.`;
    g3.intervention = "Push for hybrid (2–3 days) or fund relocation. Otherwise widen geography.";
  } else if (i.remote_policy === "onsite" && isHub) {
    g3.reason = `Onsite in ${i.geography}. Hub city — pool intact, but commute friction is real for senior leaders.`;
  } else {
    g3.reason = `Remote policy: ${i.remote_policy}${i.geography ? " · " + i.geography : ""}. Pool compatible.`;
  }
  gates.push({ q: "Is geography / remote policy compatible with the talent pool?", short: "Geography", ...g3 });

  // Gate 4: Timeline
  const baseWeeks = { CFO: 14, "VP Sales": 12, Product: 12, Engineering: 14, Ops: 12, Other: 12 }[i.role_family] || 12;
  const adjWeeks = baseWeeks + (i.confidential ? 2 : 0) + (i.off_limits.length > 5 ? 2 : 0);
  let g4 = { yes: true, reason: "", intervention: "" };
  if (i.timeline_weeks && i.timeline_weeks < adjWeeks) {
    g4.yes = false;
    g4.reason = `Timeline ${i.timeline_weeks}w vs. realistic floor ${adjWeeks}w for ${i.role_family}${i.confidential?" (confidential +2w)":""}${i.off_limits.length>5?" (heavy off-limits +2w)":""}.`;
    g4.intervention = "Negotiate timeline up-front, or pre-narrow archetype to a single high-conviction profile.";
  } else {
    g4.reason = `Timeline ${i.timeline_weeks||"?"}w vs. floor ${adjWeeks}w. Mathematically possible.`;
  }
  gates.push({ q: "Is the timeline mathematically possible given pool size and process?", short: "Timeline", ...g4 });

  // Gate 5: HM cal
  let g5 = { yes: true, reason: "", intervention: "" };
  if (i.hm_cal === "Low") {
    g5.yes = false;
    g5.reason = "HM self-rated as Low calibration. First 4 weeks at risk of teaching, not searching.";
    g5.intervention = "Send 3 calibration profiles before kickoff. Force the must-haves conversation in writing.";
  } else if (i.hm_cal === "Medium") {
    g5.reason = "HM at Medium. Watch for unstated criteria emerging week 1–2.";
  } else {
    g5.reason = "HM calibrated High. Move directly to thesis validation.";
  }
  gates.push({ q: "Is the hiring manager calibrated, or do they need education first?", short: "HM calibration", ...g5 });

  const score = gates.filter(g => g.yes).length;
  let banner = "green";
  if (score <= 2) banner = "red"; else if (score === 3) banner = "yellow";
  let msg;
  if (score === 5) msg = "Search is well-scoped. Proceed.";
  else if (score === 4) msg = "Search is doable. One issue to resolve pre-kickoff.";
  else if (score === 3) msg = "Search is at risk. Two failures — surface to client before kickoff.";
  else msg = "Search is at material risk. Recommend pause-or-renegotiate before sourcing.";

  return { gates, score, banner, msg };
}

/* Backer/ownership terminology — "sponsor" is PE-only; VC has lead investors,
   founder-owned has founders, public has boards. Don't leak PE vocab into other contexts. */
function backerLabel(ownership) {
  return ({
    "PE-backed":     { backer: "sponsor",       backerAdj: "sponsor",  noun: "platform" },
    "VC-backed":     { backer: "lead investor", backerAdj: "investor", noun: "company" },
    "founder-owned": { backer: "founder",       backerAdj: "founder",  noun: "company" },
    "public":        { backer: "board",         backerAdj: "board",    noun: "company" },
    "other":         { backer: "investor",      backerAdj: "investor", noun: "company" },
  })[ownership] || { backer: "investor", backerAdj: "investor", noun: "company" };
}

function thesisLine(i) {
  const stageVerb = {
    startup: "takes the function from 0→1",
    growth: "scales the function through the next inflection",
    "mid-market": "operationalizes the function past the founder phase",
    enterprise: "runs at category-leader scale",
    turnaround: "stabilizes first, then re-engines",
  }[i.stage];
  const ownVerb = {
    "PE-backed": "with sponsor-grade reporting discipline",
    "VC-backed": "with burn-rate and metric-driven discipline",
    "founder-owned": "who can operate without the founder in the room",
    public: "with guidance-aware EPS discipline",
    other: "with the operating discipline this stage demands",
  }[i.ownership];
  const b = backerLabel(i.ownership);
  const company = i.company || "[Company]";
  const role = i.role_title || i.role_family;
  // Preserve case on user-supplied industry; restructure to avoid "platform platform" duplication
  const industryClause = i.industry ? ` in ${i.industry}` : "";
  return `The winning ${role} is an operator who ${stageVerb} at a ${i.ownership} ${b.noun}${industryClause} ${ownVerb} — and is currently in the right window to move on ${company}.`;
}

function thesis(i) {
  const company = i.company || "[Company]";
  const s1 = `This is a ${i.role_family} search for ${company}, a ${i.ownership} ${i.stage}-stage ${i.industry || "company"}.`;
  const s2 = i.mandate
    ? `The real mandate, behind the JD: ${i.mandate.split(/[.\n]/)[0].trim()}.`
    : "The real mandate sits behind the JD — pressure-test in kickoff.";
  // Drop the awkward "first sentence as pattern" extraction. Reference the actual map below.
  const s3 = ` We hunt first in feeders that match ${company}'s operating-pressure profile — see the Market State Map below.`;
  return s1 + " " + s2 + s3;
}

const ARCHETYPES_BY_ROLE = {
  CFO: [
    { name: "PE-backed scaler", desc: "Operator who took a sponsored platform from $X to $Y with sponsor-grade reporting cadence.", where: "PE-backed mid-market in same vertical, 14–20 months post-exit.", confidence: "High" },
    { name: "Big-4-trained operator", desc: "Audit/assurance background, moved into industry CFO seats. Sharp on controls and close.", where: "Public or pre-IPO finance teams; current Controller / VP Finance.", confidence: "Medium" },
    { name: "Strategic CFO", desc: "Banker/PE turned operator. Capital-markets fluent, sponsor-relationship native.", where: "Sponsor portfolios, post-banking transitions.", confidence: "Medium" },
  ],
  "VP Sales": [
    { name: "First scaled GTM leader", desc: "Built the first repeatable motion in a founder-led company. Process without bureaucracy.", where: "Vertical SaaS Series B–C, 18–30 months in role.", confidence: "High" },
    { name: "Player-coach", desc: "Carries quota themselves while scaling team. No ivory-tower VPs.", where: "$5–25M ARR, founder still in deals.", confidence: "Medium" },
    { name: "Enterprise hunter", desc: "Six-figure ACV, multi-stakeholder selling. Knows when to bring in execs.", where: "Enterprise SaaS / industrial sales orgs.", confidence: "Medium" },
  ],
  Product: [
    { name: "Founding PM", desc: "0→1 builder. Comfortable without research org or design system.", where: "YC alums, early product hires at scale-ups.", confidence: "High" },
    { name: "Growth PM", desc: "Activation, retention, monetization fluency. Experiment-first.", where: "PLG companies, growth pods at scale-ups.", confidence: "Medium" },
    { name: "Platform PM", desc: "Internal tools, APIs, infra. Engineering-respected.", where: "Mid-market platform companies.", confidence: "Medium" },
  ],
  Engineering: [
    { name: "Player-coach VPE", desc: "Still ships code, but has scaled an org past 30 engineers.", where: "Series C–D scale-ups, current Director/VP at $100M+ companies.", confidence: "High" },
    { name: "Scale architect", desc: "Took a system from $1M to $100M users. Owns the rebuild calls.", where: "Late-stage hypergrowth alumni.", confidence: "Medium" },
    { name: "Founding engineer", desc: "CTO-track. 0→1 systems. Comfort with sparse spec.", where: "Early-stage exits, technical co-founders looking for second act.", confidence: "Medium" },
  ],
  Ops: [
    { name: "COO operator", desc: "P&L-accountable, multi-function. Right hand to founder/CEO.", where: "Sponsor portfolios, COO-2 seats at larger companies.", confidence: "High" },
    { name: "Process scaler", desc: "Six Sigma / lean operator who industrializes a function.", where: "Manufacturing, logistics, multi-site services.", confidence: "Medium" },
    { name: "Vertical ops leader", desc: "Industry-specific operating depth — knows the unit economics cold.", where: "Vertical operators in same industry, 8–15 years in.", confidence: "Medium" },
  ],
  Other: [
    { name: "Domain operator", desc: "Direct subject-matter operator with the specific functional depth.", where: "Adjacent companies in same vertical/stage.", confidence: "Medium" },
    { name: "Adjacent leader", desc: "Comparable scope from an adjacent function or industry.", where: "Lateral move candidates from feeder companies.", confidence: "Medium" },
    { name: "Stretch hire", desc: "High-trajectory operator one level down. Higher risk, higher upside.", where: "Director-level at 1–2 tier-up companies.", confidence: "Low" },
  ],
};

function archetypes(i) {
  const base = ARCHETYPES_BY_ROLE[i.role_family] || ARCHETYPES_BY_ROLE.Other;
  return base.map((a, idx) => {
    if (idx === 0 && i.ownership === "founder-owned") return { ...a, desc: a.desc + " Founder-orbit fit non-negotiable." };
    if (idx === 0 && i.ownership === "PE-backed") return { ...a, desc: a.desc + " Sponsor-language fluency required." };
    return a;
  });
}

function risks(i, diag) {
  const r = [];
  diag.gates.forEach(g => {
    if (!g.yes && g.intervention) {
      r.push({
        risk: g.short,
        severity: "High",
        impact: g.reason,
        mitigation: g.intervention,
      });
    }
  });
  if (i.off_limits.length > 0) {
    r.push({
      risk: `Off-limits coverage (${i.off_limits.length})`,
      severity: i.off_limits.length > 5 ? "High" : "Medium",
      impact: `Removes ${i.off_limits.length > 5 ? "material" : "some"} feeder coverage. Watch for mid-search expansion.`,
      mitigation: "Lock off-limits in writing. Renegotiate fee if expanded mid-search.",
    });
  }
  if (i.confidential) {
    r.push({
      risk: "Confidential search constraints",
      severity: "Medium",
      impact: "+2 weeks to timeline; outreach harder to ground in specifics.",
      mitigation: "Pre-build a non-attributable hook. Use sponsor/stage language vs. company name.",
    });
  }
  if (i.past_failures) {
    r.push({
      risk: "Pattern of prior failed hires",
      severity: "Medium",
      impact: "HM may have unstated criteria the brief has not surfaced.",
      mitigation: "Force unstated-criteria conversation in kickoff. Reference past failure pattern explicitly.",
    });
  }
  if (r.length === 0) {
    r.push({
      risk: "No diagnostic failures detected",
      severity: "Low",
      impact: "Proceed. Normal week-1 watchouts apply.",
      mitigation: "Run the gates; if any fail in week 1, recalibrate.",
    });
  }
  return r;
}

function assumptions(i) {
  const a = [];
  if (i.cash_high && i.cash_low) {
    a.push({
      assumption: `Comp band $${(i.cash_low/1000).toFixed(0)}–${(i.cash_high/1000).toFixed(0)}K cash is what the market clears for this profile`,
      why: "Determines pool depth and time-to-thesis.",
      validate: "Pull comp on first 5 calibration calls. Adjust band if 3+ candidates push back.",
      owner: "Search lead",
    });
  }
  if (i.must_haves.length > 0) {
    a.push({
      assumption: `All ${i.must_haves.length} must-haves are real, not aspirational`,
      why: "Each fake must-have shrinks pool by ~30%.",
      validate: "Pressure-test 3 must-haves in kickoff: 'would you pass on someone strong if they lacked X?'",
      owner: "Partner",
    });
  }
  if (i.hm_cal !== "High") {
    a.push({
      assumption: "HM will refine criteria after seeing 3–5 calibration profiles",
      why: "Doubles the addressable pool if calibration shifts.",
      validate: "Calibration call by Day 5–7.",
      owner: "Partner + HM",
    });
  }
  if (i.ownership === "PE-backed") {
    a.push({
      assumption: "HM/sponsor will accept candidates from non-PE backgrounds with strong scale story",
      why: "PE-only filter cuts pool ~60%.",
      validate: "Test with 2 non-PE calibration profiles in week 1.",
      owner: "Search lead",
    });
  }
  return a;
}

function operatingPlan() {
  return [
    { day: "0–1", action: "Validate brief, run kickoff, sync on diagnostic", owner: "Partner", output: "Confirmed thesis", gate: "Did kickoff confirm thesis? If no → revise brief before sourcing." },
    { day: "1–3", action: "Build target universe from Market State Map", owner: "Researcher", output: "Tier 1/2/3 list with state tags + classification", gate: "Pool >40 viable? If no → expand archetypes or push back on must-haves." },
    { day: "3–5", action: "First wave outreach (Tier 1 + Post-leadership-change)", owner: "Search lead", output: "8–12 conversations live", gate: "Response rate >15%? If no → outreach plays are wrong, rewrite hook." },
    { day: "5–7", action: "Calibration call — review first 5 candidates with HM", owner: "Partner + HM", output: "HM signal on profile", gate: "Did HM react predictably? If no → recalibrate thesis or escalate to sponsor." },
    { day: "7–10", action: "Second wave + thesis adjustment + week-1 client memo", owner: "Search lead + Partner", output: "Updated brief, refined target list, week-1 memo", gate: "On track or reset with client? Decision required." },
  ];
}

function stakeholderNotes(i) {
  /* INTERNAL ONLY — never emitted to client surface. */
  if (!i.hm_notes && !i.past_failures) return [];
  const notes = [];
  if (i.hm_notes) notes.push({ kind: "Observed behavior", body: i.hm_notes });
  if (i.past_failures) notes.push({ kind: "Failure pattern", body: i.past_failures });
  if (i.other_context) notes.push({ kind: "Sponsor / board context", body: i.other_context });
  return notes;
}

function stopConditions(i, diag) {
  /* INTERNAL ONLY. */
  const list = [
    "Off-limits expands mid-search beyond what was scoped at kickoff.",
    "HM rejects 3+ on-thesis candidates without articulating new criteria.",
    "Comp band moves down after kickoff.",
  ];
  if (diag.gates.find(g => g.short === "Timeline" && !g.yes)) {
    list.push("Timeline compresses further from current commitment.");
  }
  if (i.confidential) list.push("Confidentiality breach — search becomes attributable to client.");
  return list;
}

function outreachPlays(i) {
  /* INTERNAL ONLY. Pattern hooks, not finished copy. */
  const b = backerLabel(i.ownership);
  // Hook label adapts to ownership — never call a VC "sponsor"
  const backerHookLabel = ({
    "PE-backed":     "Sponsor-pattern hook",
    "VC-backed":     "Investor-pattern hook",
    "founder-owned": "Founder-fit hook",
    "public":        "Board-pattern hook",
    "other":         "Backer-pattern hook",
  })[i.ownership] || "Backer-pattern hook";
  const role = i.role_title || i.role_family;
  const company = i.company || "the seat";
  return [
    {
      hook: "Operating-state hook",
      when: "Target sits in a Post-leadership-change or Pre-restructure window.",
      body: `"Saw the [event]. The next 60 days are when the smart money in your seat starts looking. ${company} just opened a ${role} seat and the brief is sharper than what you're sitting in. Worth 20 minutes?"`
    },
    {
      hook: backerHookLabel,
      when: `Target has worked under a comparable ${b.backerAdj} in their history.`,
      body: `"You've operated under a [comparable ${b.backerAdj} archetype]. We're early on a ${role} seat where the ${b.backer} is — frankly — easier than most. Want the read-out?"`
    },
    {
      hook: "Failure-mode hook",
      when: "Target's current company shows the same pattern as the failure mode at our client.",
      body: `"You've lived [failure pattern at their current company]. We're working on a seat where the next person can't have that gap. Want to compare notes?"`
    },
  ];
}

window.IE_ENGINE = {
  runDiagnostic, thesisLine, thesis, archetypes,
  risks, assumptions, operatingPlan,
  stakeholderNotes, stopConditions, outreachPlays,
};
