// Copilot rules — Dial 2 (missing-data nudges) + Dial 3 (5 hardcoded clinical observations).
// Pure: takes (state, calc) and returns a list of flag/nudge objects.

(function () {
  const { toCm, toKg, devineIBW } = window.RD;

  // Dial 2 — Missing-data nudges. Triggered when a calc is requested but blocked.
  function missingForCalc(what, state) {
    const missing = [];
    if (what === "energy" || what === "all") {
      if (!state.age) missing.push({ field: "age", label: "Age" });
      if (!state.sex) missing.push({ field: "sex", label: "Sex" });
      if (!state.height) missing.push({ field: "height", label: "Height" });
      if (!state.weight) missing.push({ field: "weight", label: "Weight" });
      if (!state.activity) missing.push({ field: "activity", label: "Activity level", chips: true });
    }
    if (what === "protein" || what === "all") {
      if (!state.diagnosis) missing.push({ field: "diagnosis", label: "Diagnosis" });
    }
    return missing;
  }

  function nudgeReply(missing, what) {
    const f = missing[0];
    if (f.field === "activity") {
      return {
        role: "assistant",
        kind: "chips",
        text: `I can calculate ${what === "energy" || what === "all" ? "energy needs" : "that"}, but activity level affects the result.`,
        chips: [
          { label: "Sedentary", action: { kind: "resolve", field: "activity", value: "sedentary" } },
          { label: "Light", action: { kind: "resolve", field: "activity", value: "light" } },
          { label: "Moderate", action: { kind: "resolve", field: "activity", value: "moderate" } },
          { label: "Very active", action: { kind: "resolve", field: "activity", value: "very" } },
          { label: "Extra active", action: { kind: "resolve", field: "activity", value: "extra" } },
        ],
      };
    }
    if (f.field === "diagnosis") {
      return {
        role: "assistant",
        kind: "text",
        text: "I can run protein once you give me a primary diagnosis — that drives the per-kg basis. Type something like \"T2DM\" or pick one in the chart.",
      };
    }
    return {
      role: "assistant",
      kind: "text",
      text: `I need ${missing.map(m => m.label).join(", ")} before I can run that.`,
    };
  }

  // Dial 3 — Exactly 5 hardcoded clinical observation rules.
  function evaluateFlags(state, calc) {
    const flags = [];
    const ageNum = parseFloat(state.age);
    const weightKg = state.weight ? toKg(parseFloat(state.weight), state.weightUnit) : null;
    const heightCm = state.height ? toCm(parseFloat(state.height), state.heightUnit) : null;
    const bmi = (weightKg && heightCm)
      ? weightKg / Math.pow(heightCm / 100, 2)
      : null;

    // Rule 1 — BMI extremes
    if (bmi) {
      if (bmi < 16) {
        flags.push({
          id: "bmi-severe-underweight",
          severity: "warn",
          title: `BMI is ${bmi.toFixed(1)} — suggests severe underweight.`,
          body: "Want to flag this in the PES?",
          actions: [
            { label: "Flag in PES", action: { kind: "flag-pes", problem: "Inadequate energy intake" } },
            { label: "Ignore", action: { kind: "dismiss-flag", id: "bmi-severe-underweight" } },
          ],
          cite: "ASPEN/Academy Consensus on Adult Malnutrition.",
        });
      } else if (bmi >= 40) {
        flags.push({
          id: "bmi-severe-obesity",
          severity: "warn",
          title: `BMI is ${bmi.toFixed(1)} — suggests severe obesity.`,
          body: "Want to flag this in the PES?",
          actions: [
            { label: "Flag in PES", action: { kind: "flag-pes", problem: "Excessive energy intake" } },
            { label: "Ignore", action: { kind: "dismiss-flag", id: "bmi-severe-obesity" } },
          ],
          cite: "ASPEN/Academy Consensus on Adult Malnutrition.",
        });
      }
    }

    // Rule 2 — Significant unintentional weight loss
    if (state.weightChange && /unintentional|lost|loss|dropped|down/i.test(state.weightChange)) {
      // Try to detect % or duration triggers
      const pct = state.weightChange.match(/(\d+(?:\.\d+)?)\s*%/);
      const lost = state.weightChange.match(/(\d+(?:\.\d+)?)\s*(lb|lbs|pounds|kg)/i);
      const months = state.weightChange.match(/(\d+)\s*months?/i);
      const days = state.weightChange.match(/(\d+)\s*days?/i);
      let triggered = false;
      if (pct) {
        const p = parseFloat(pct[1]);
        if (p > 5) triggered = true;
      }
      if (lost && weightKg) {
        const lostKg = /lb/i.test(lost[2]) ? parseFloat(lost[1]) * 0.4536 : parseFloat(lost[1]);
        const baselineKg = weightKg + lostKg;
        const pctLoss = (lostKg / baselineKg) * 100;
        const monthsN = months ? parseInt(months[1], 10) : (days ? parseInt(days[1], 10) / 30 : 6);
        if ((monthsN <= 1 && pctLoss > 5) || (monthsN <= 6 && pctLoss > 10)) triggered = true;
      }
      if (!pct && !lost && /unintentional|significant|recent/i.test(state.weightChange)) triggered = true;
      if (triggered) {
        flags.push({
          id: "weight-loss",
          severity: "warn",
          title: "Significant unintentional weight loss noted.",
          body: "Flag in PES?",
          actions: [
            { label: "Flag in PES", action: { kind: "flag-pes", problem: "Unintended weight loss" } },
            { label: "Ignore", action: { kind: "dismiss-flag", id: "weight-loss" } },
          ],
          cite: "ASPEN/Academy Consensus on Adult Malnutrition.",
        });
      }
    }

    // Rule 3 — CKD without GFR mentioned
    if (state.diagnosis?.id === "ckd") {
      const hasGFR = (state.labs || "").match(/\bgfr\b/i);
      if (!hasGFR) {
        flags.push({
          id: "ckd-no-gfr",
          severity: "info",
          title: "CKD without a GFR value.",
          body: "GFR helps me give the right protein recommendation. What's the latest?",
          actions: [
            { label: "Add to labs", action: { kind: "focus", target: "labs" } },
            { label: "Dismiss", action: { kind: "dismiss-flag", id: "ckd-no-gfr" } },
          ],
          cite: "KDOQI 2020.",
        });
      }
    }

    // Rule 4 — Conflicting activity vs notes
    if (state.activity === "sedentary" && /\b(trains?|runs?|exercises?|works out|gym|crossfit|marathon|active)\b/i.test(state.dietNotes || "")) {
      flags.push({
        id: "activity-conflict",
        severity: "info",
        title: "Activity is set to Sedentary, but notes mention training.",
        body: "Which is right?",
        actions: [
          { label: "Lightly active", action: { kind: "resolve", field: "activity", value: "light" } },
          { label: "Moderately active", action: { kind: "resolve", field: "activity", value: "moderate" } },
          { label: "Very active", action: { kind: "resolve", field: "activity", value: "very" } },
          { label: "Keep sedentary", action: { kind: "dismiss-flag", id: "activity-conflict" } },
        ],
        cite: null,
      });
    }

    // Rule 5 — Adjusted body weight applies
    if (bmi && bmi >= 30 && state.diagnosis?.id === "obesity") {
      const ibw = (state.sex && heightCm) ? devineIBW(state.sex, heightCm) : null;
      if (ibw && weightKg) {
        const abw = ibw + 0.25 * (weightKg - ibw);
        flags.push({
          id: "abw-recommend",
          severity: "info",
          title: `Adjusted body weight applies (${abw.toFixed(1)} kg vs actual ${weightKg.toFixed(1)} kg).`,
          body: "For obesity, adjusted body weight is recommended for protein. Currently using whichever you've selected on the Protein card.",
          actions: [
            { label: "Use adjusted (recommended)", action: { kind: "set-basis", value: "adjusted" } },
            { label: "Use current", action: { kind: "set-basis", value: "current" } },
            { label: "Dismiss", action: { kind: "dismiss-flag", id: "abw-recommend" } },
          ],
          cite: "Academy Adult Weight Management EBNPG.",
        });
      }
    }

    return flags;
  }

  window.RD_Rules = { missingForCalc, nudgeReply, evaluateFlags };
})();
