/* TDEE Calculator core component + page extensions */

const { useState: useStateC, useEffect: useEffectC, useMemo: useMemoC, useCallback: useCallbackC } = React;

const DEFAULT_INPUTS = {
  sex: "male",
  age: 30,
  heightCm: 178,
  weightKg: 80,
  activityLevel: "moderate",
  bodyFatPercent: null,
  formula: null,
  lifePhase: null,
};

function useTDEEState(overrides = {}) {
  const initial = useMemoC(() => {
    const merged = { ...DEFAULT_INPUTS, ...overrides };
    if (typeof window === "undefined") return merged;
    const m = window.location.hash.match(/[#&]s=([^&]+)/);
    if (m) {
      const decoded = window.TDEE.decodeState(decodeURIComponent(m[1]));
      if (decoded && decoded.inputs) return { ...merged, ...decoded.inputs };
    }
    return merged;
  }, []);

  const [inputs, setInputs] = useStateC(initial);
  const [units, setUnits] = useStateC(() => {
    try { return localStorage.getItem("tdeegoal_units") || "imperial"; } catch (e) { return "imperial"; }
  });

  useEffectC(() => {
    try { localStorage.setItem("tdeegoal_units", units); } catch (e) {}
  }, [units]);

  useEffectC(() => {
    const onRestore = (ev) => {
      if (ev.detail && ev.detail.inputs) {
        setInputs((s) => ({ ...s, ...ev.detail.inputs }));
        if (ev.detail.units) setUnits(ev.detail.units);
      }
    };
    window.addEventListener("tdee:restore", onRestore);
    return () => window.removeEventListener("tdee:restore", onRestore);
  }, []);

  const update = useCallbackC((patch) => setInputs((s) => ({ ...s, ...patch })), []);

  const valid = useMemoC(() => {
    if (inputs.age == null || inputs.age < 14 || inputs.age > 100) return false;
    if (inputs.heightCm == null || inputs.heightCm < 100 || inputs.heightCm > 250) return false;
    if (inputs.weightKg == null || inputs.weightKg < 30 || inputs.weightKg > 250) return false;
    return true;
  }, [inputs]);

  const result = useMemoC(() => {
    if (!valid) return null;
    return window.TDEE.calculateTDEE({
      sex: inputs.sex,
      ageYears: inputs.age,
      heightCm: inputs.heightCm,
      weightKg: inputs.weightKg,
      activityLevel: inputs.activityLevel,
      bodyFatPercent: inputs.bodyFatPercent,
      formula: inputs.formula,
      lifePhase: inputs.lifePhase,
    });
  }, [inputs, valid]);

  return { inputs, update, units, setUnits, result, valid };
}

// Convert helpers for display
function dispWeight(kg, units) {
  if (kg == null) return "";
  return units === "imperial" ? Math.round(window.TDEE.kgToLb(kg) * 10) / 10 : Math.round(kg * 10) / 10;
}
function dispHeight(cm, units) {
  if (cm == null) return "";
  return units === "imperial" ? Math.round(window.TDEE.cmToIn(cm) * 10) / 10 : Math.round(cm);
}
function setWeight(val, units, update) {
  if (val == null) return update({ weightKg: null });
  update({ weightKg: units === "imperial" ? window.TDEE.lbToKg(val) : val });
}
function setHeight(val, units, update) {
  if (val == null) return update({ heightCm: null });
  update({ heightCm: units === "imperial" ? window.TDEE.inToCm(val) : val });
}

// ─── Inputs panel ────────────────────────────────────────────────────────
function InputsPanel({ ctx, variant, mobile }) {
  const { inputs, update, units, setUnits } = ctx;
  const [tab, setTab] = useStateC("standard");
  const showSex = variant !== "women";

  return (
    <div className="calc-input">
      <div className="calc-tabs">
        <button className={"calc-tab" + (tab === "standard" ? " is-active" : "")} onClick={() => setTab("standard")}>
          Standard
        </button>
        <button className={"calc-tab" + (tab === "advanced" ? " is-active" : "")} onClick={() => setTab("advanced")}>
          Advanced
        </button>
        <div style={{ marginLeft: "auto", paddingBottom: 4 }}>
          <SegControl
            value={units}
            onChange={setUnits}
            ariaLabel="Units"
            options={[{ value: "imperial", label: "lb / in" }, { value: "metric", label: "kg / cm" }]}
          />
        </div>
      </div>

      <div className="label-row">
        <span className="t-label">Personal</span>
        <span className="label-row-line"></span>
      </div>

      {showSex && (
        <div style={{ marginBottom: 14 }}>
          <SegControl
            value={inputs.sex}
            onChange={(v) => update({ sex: v })}
            ariaLabel="Sex"
            options={[{ value: "male", label: "Male" }, { value: "female", label: "Female" }]}
          />
        </div>
      )}

      <div className="field-group three">
        <NumberInput
          id="age" label="Age"
          value={inputs.age}
          onChange={(v) => update({ age: v })}
          suffix="yrs"
          min={14} max={100}
        />
        <NumberInput
          id="height" label="Height"
          value={dispHeight(inputs.heightCm, units)}
          onChange={(v) => setHeight(v, units, update)}
          suffix={units === "imperial" ? "in" : "cm"}
        />
        <NumberInput
          id="weight" label="Weight"
          value={dispWeight(inputs.weightKg, units)}
          onChange={(v) => setWeight(v, units, update)}
          suffix={units === "imperial" ? "lb" : "kg"}
        />
      </div>

      <div className="label-row">
        <span className="t-label">Activity</span>
        <span className="label-row-line"></span>
      </div>
      <ActivitySlider value={inputs.activityLevel} onChange={(v) => update({ activityLevel: v })} />

      {(tab === "advanced" || variant === "body-fat") && (
        <>
          <div className="label-row">
            <span className="t-label">Advanced</span>
            <span className="label-row-line"></span>
          </div>
          <div className="field-group">
            <NumberInput
              id="bf" label="Body fat %"
              value={inputs.bodyFatPercent}
              onChange={(v) => update({ bodyFatPercent: v })}
              suffix="%"
              hint={variant === "body-fat" ? "required" : "optional"}
              min={3} max={60}
            />
            <label className="field">
              <span className="t-label">Formula</span>
              <select
                className="input-wrap mono"
                style={{ paddingLeft: 12, paddingRight: 12 }}
                value={inputs.formula || "auto"}
                onChange={(e) => update({ formula: e.target.value === "auto" ? null : e.target.value })}
              >
                <option value="auto">Auto</option>
                <option value="mifflin">Mifflin-St Jeor</option>
                <option value="katch-mcardle">Katch-McArdle</option>
                <option value="cunningham">Cunningham</option>
              </select>
              {(inputs.formula === "katch-mcardle" || inputs.formula === "cunningham") && inputs.bodyFatPercent == null && (
                <span className="t-micro" style={{ color: "var(--warning)", marginTop: 6, display: "block" }}>
                  Enter body fat % to use {inputs.formula === "katch-mcardle" ? "Katch-McArdle" : "Cunningham"}.
                </span>
              )}
            </label>
          </div>
        </>
      )}

      {variant === "women" && (
        <>
          <div className="label-row">
            <span className="t-label">Life phase</span>
            <span className="label-row-line"></span>
          </div>
          <CyclePhaseGrid value={inputs.lifePhase} onChange={(v) => update({ lifePhase: v })} />
        </>
      )}
    </div>
  );
}

const PHASES = [
  { id: null, label: "Regular cycle", adj: "±0" },
  { id: "perimenopause", label: "Perimenopause", adj: "−50" },
  { id: "pregnant-t1", label: "Pregnant · T1", adj: "+0" },
  { id: "pregnant-t2", label: "Pregnant · T2", adj: "+340" },
  { id: "pregnant-t3", label: "Pregnant · T3", adj: "+450" },
  { id: "breastfeeding-0-6mo", label: "Breastfeed · 0–6mo", adj: "+500" },
  { id: "breastfeeding-6-12mo", label: "Breastfeed · 6–12mo", adj: "+400" },
  { id: "postmenopause", label: "Post-menopause", adj: "±0" },
];

function CyclePhaseGrid({ value, onChange }) {
  return (
    <div className="cycle-grid">
      {PHASES.map((p) => (
        <button
          key={p.id || "regular"}
          className={"cycle-btn" + (value === p.id ? " is-active" : "")}
          onClick={() => onChange(p.id)}
        >
          <span className="cycle-btn-name">{p.label}</span>
          <span className="cycle-btn-adj mono">{p.adj} cal/day</span>
        </button>
      ))}
    </div>
  );
}

// ─── Results panel ───────────────────────────────────────────────────────
function ResultsPanel({ ctx, variant }) {
  const { result, inputs, units } = ctx;
  const [goal, setGoal] = useStateC(
    variant === "weight-loss" ? "cut" :
    variant === "body-fat" ? "maintain" :
    "maintain"
  );
  const [deficit, setDeficit] = useStateC(15);
  const [goalWeightKg, setGoalWeightKg] = useStateC(inputs.weightKg ? inputs.weightKg - 5 : 75);

  useEffectC(() => {
    if (inputs.weightKg && (!goalWeightKg || goalWeightKg >= inputs.weightKg)) {
      setGoalWeightKg(inputs.weightKg - 4.5);
    }
  }, [inputs.weightKg]);

  const cut = useMemoC(() => {
    if (!result || goal !== "cut") return null;
    return window.TDEE.cutPlan({
      tdee: result.tdee,
      deficitPercent: deficit,
      currentWeightKg: inputs.weightKg,
      goalWeightKg,
    });
  }, [result, deficit, inputs.weightKg, goalWeightKg, goal]);

  const planCal = useMemoC(() => {
    if (!result) return null;
    if (goal === "maintain") return result.tdee;
    if (goal === "cut" && cut) return cut.dailyCalories;
    if (goal === "recomp") return Math.round(result.tdee * 0.95);
    if (goal === "reverse") return Math.round(result.tdee * 0.85);
    return result.tdee;
  }, [goal, cut, result]);

  return (
    <div className="calc-result">
      <ResultDisplay result={result} units={units} />

      {result && (
        <>
          <div>
            <div className="t-label" style={{ marginBottom: 8 }}>Pick a goal</div>
            <GoalGrid value={goal} onChange={setGoal} />
          </div>

          {goal === "cut" && (
            <CutControls
              deficit={deficit} setDeficit={setDeficit}
              goalWeightKg={goalWeightKg} setGoalWeightKg={setGoalWeightKg}
              units={units}
              cut={cut}
            />
          )}

          {goal === "reverse" && <ReverseControls tdee={result.tdee} />}

          {goal === "recomp" && (
            <div className="disclaimer">
              <span className="disclaimer-mark">i</span>
              <span className="t-micro">
                Body recomposition works best for beginners, returners, or overweight lifters. 5% deficit, high protein, expect 3–6 months for visible change.
              </span>
            </div>
          )}

          <PlanSummary
            calories={planCal}
            goal={goal}
            cut={cut}
            weightKg={inputs.weightKg}
            units={units}
          />

          {goal === "cut" && cut && cut.weeksToGoal > 0 && (
            <PlanTimeline
              currentWeightLb={window.TDEE.kgToLb(inputs.weightKg)}
              goalWeightLb={window.TDEE.kgToLb(goalWeightKg)}
              weeksToGoal={cut.weeksToGoal}
              goalDate={cut.goalDate}
              weeklyLossLb={cut.weeklyLossLb}
            />
          )}

          <PlanActions
            inputs={inputs} units={units} result={result}
            goal={goal} planCal={planCal} cut={cut} variant={variant}
          />
        </>
      )}

      <Disclaimer />
    </div>
  );
}

function PlanActions({ inputs, units, result, goal, planCal, cut, variant }) {
  const [savedFlash, setSavedFlash] = useStateC(false);
  const [sharedFlash, setSharedFlash] = useStateC(null);

  const onSave = () => {
    window.TDEE.addPlanToHistory({
      inputs, units, variant,
      goal, planCal, tdee: result?.tdee, formula: result?.formula,
      cut: cut ? { deficitPercent: cut.deficitPercent, weeksToGoal: cut.weeksToGoal, goalDate: cut.goalDate } : null,
    });
    window.dispatchEvent(new CustomEvent("tdee:history-changed"));
    setSavedFlash(true);
    setTimeout(() => setSavedFlash(false), 1600);
  };

  const onShare = async () => {
    const state = { inputs, units, variant, goal };
    const url = window.location.origin + window.location.pathname + "#s=" + encodeURIComponent(window.TDEE.encodeState(state));
    const shareData = { title: "My TDEE plan", text: `My TDEE: ${result?.tdee} cal/day`, url };
    const fallbackCopy = (text) => {
      try {
        if (navigator.clipboard && navigator.clipboard.writeText) {
          return navigator.clipboard.writeText(text).then(() => true);
        }
      } catch (e) {}
      try {
        const ta = document.createElement("textarea");
        ta.value = text;
        ta.style.position = "fixed";
        ta.style.left = "-9999px";
        document.body.appendChild(ta);
        ta.select();
        const ok = document.execCommand("copy");
        document.body.removeChild(ta);
        return Promise.resolve(ok);
      } catch (e) { return Promise.resolve(false); }
    };
    try {
      if (navigator.share && (!navigator.canShare || navigator.canShare(shareData))) {
        await navigator.share(shareData);
        setSharedFlash("shared");
      } else {
        const ok = await fallbackCopy(url);
        if (ok) setSharedFlash("copied");
        else { window.prompt("Copy your share link:", url); setSharedFlash("copied"); }
      }
    } catch (e) {
      const ok = await fallbackCopy(url);
      if (ok) setSharedFlash("copied");
      else if (e.name !== "AbortError") { window.prompt("Copy your share link:", url); setSharedFlash("copied"); }
    }
    setTimeout(() => setSharedFlash(null), 1800);
  };

  return (
    <div className="cta-row">
      <button className="btn btn-primary" onClick={onSave}>
        {savedFlash ? "Saved" : "Save plan"}
        <svg width="12" height="12" viewBox="0 0 16 16" fill="none">
          <path d="M3 8l3 3 7-7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
      </button>
      <button className="btn btn-secondary" onClick={onShare}>
        {sharedFlash === "copied" ? "Link copied" : sharedFlash === "shared" ? "Shared" : sharedFlash === "error" ? "Try again" : "Share"}
      </button>
    </div>
  );
}

function CutControls({ deficit, setDeficit, goalWeightKg, setGoalWeightKg, units, cut }) {
  const presets = [
    { pct: 10, label: "Easy" },
    { pct: 15, label: "Standard" },
    { pct: 20, label: "Aggressive" },
    { pct: 25, label: "Crash" },
  ];
  return (
    <div>
      <div className="t-label" style={{ marginBottom: 8 }}>Deficit size</div>
      <div className="deficit-slider-row">
        {presets.map((p) => (
          <button
            key={p.pct}
            className={"deficit-pill" + (deficit === p.pct ? " is-active" : "")}
            onClick={() => setDeficit(p.pct)}
          >
            <div className="deficit-pill-pct">{p.pct}%</div>
            <div className="deficit-pill-label">{p.label}</div>
          </button>
        ))}
      </div>
      <div style={{ marginTop: 14 }}>
        <NumberInput
          id="goal-weight"
          label="Goal weight"
          value={units === "imperial" ? Math.round(window.TDEE.kgToLb(goalWeightKg) * 10) / 10 : Math.round(goalWeightKg * 10) / 10}
          onChange={(v) => setGoalWeightKg(v == null ? null : (units === "imperial" ? window.TDEE.lbToKg(v) : v))}
          suffix={units === "imperial" ? "lb" : "kg"}
        />
      </div>
      {cut && cut.warnings.length > 0 && (
        <div style={{ marginTop: 10 }}>
          {cut.warnings.map((w, i) => (
            <div key={i} className="disclaimer" style={{ marginTop: 6 }}>
              <span className="disclaimer-mark">!</span>
              <span className="t-micro">{w}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function ReverseControls({ tdee }) {
  const [current, setCurrent] = useStateC(Math.round(tdee * 0.8));
  const [increase, setIncrease] = useStateC(75);
  const plan = window.TDEE.reversePlan({ currentCalories: current, tdee, weeklyIncrease: increase });
  return (
    <div>
      <div className="field-group">
        <NumberInput id="cur-cal" label="Current intake" value={current} onChange={setCurrent} suffix="cal" />
        <label className="field">
          <span className="t-label">Weekly increase</span>
          <SegControl
            value={increase}
            onChange={setIncrease}
            ariaLabel="Increase"
            options={[{ value: 50, label: "+50" }, { value: 75, label: "+75" }, { value: 100, label: "+100" }]}
          />
        </label>
      </div>
      <div className="reverse-table" style={{ marginTop: 10 }}>
        {plan.milestones.slice(0, 7).map((m, i) => (
          <div key={i} className={"reverse-row" + (i === 0 ? " is-current" : "")}>
            <span className="reverse-row-week">Wk {m.week}</span>
            <div className="reverse-row-bar">
              <div className="reverse-row-fill" style={{ width: ((m.calories / tdee) * 100) + "%" }}></div>
            </div>
            <span className="reverse-row-cal">{m.calories.toLocaleString()}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function PlanSummary({ calories, goal, cut, weightKg, units }) {
  if (calories == null) return null;
  const goalLabel = { cut: "Cut", maintain: "Maintain", recomp: "Recomp", reverse: "Reverse diet" }[goal];

  let stat1Val = "—", stat1Label = "Weekly change";
  let stat2Val = "—", stat2Label = "Date";
  let stat3Val = "—", stat3Label = "Total Δ";

  if (goal === "cut" && cut) {
    stat1Val = "−" + (units === "imperial" ? cut.weeklyLossLb.toFixed(1) + " lb" : cut.weeklyLossKg.toFixed(1) + " kg");
    stat2Val = cut.goalDate.toLocaleDateString("en-US", { month: "short", day: "numeric" });
    stat3Val = cut.weeksToGoal + " wks";
    stat3Label = "To goal";
  } else if (goal === "maintain") {
    stat1Val = "0";
    stat2Val = "Steady";
    stat3Val = "—";
  } else if (goal === "recomp") {
    stat1Val = "Slow";
    stat2Val = "3–6 mo";
    stat3Val = "−5%";
    stat3Label = "Deficit";
  } else if (goal === "reverse") {
    stat1Val = "+0.1 lb";
    stat1Label = "Drift";
    stat2Val = "8–12 wks";
    stat3Val = "→ TDEE";
  }

  return (
    <div>
      <div className="plan-summary">
        <div className="t-label" style={{ color: "var(--accent)", opacity: 0.8 }}>
          Your plan · {goalLabel}
        </div>
        <div className="plan-summary-big">{calories.toLocaleString()}</div>
        <div className="plan-summary-sub">calories per day</div>
      </div>
      <div className="plan-stat-row">
        <div className="plan-stat">
          <div className="plan-stat-val mono">{stat1Val}</div>
          <div className="plan-stat-label">{stat1Label}</div>
        </div>
        <div className="plan-stat">
          <div className="plan-stat-val mono">{stat2Val}</div>
          <div className="plan-stat-label">{stat2Label}</div>
        </div>
        <div className="plan-stat">
          <div className="plan-stat-val mono">{stat3Val}</div>
          <div className="plan-stat-label">{stat3Label}</div>
        </div>
      </div>
    </div>
  );
}

// ─── Main calculator wrapper ─────────────────────────────────────────────
function TDEECalculator({ variant = "hub", mobile = false }) {
  const overrides = {};
  if (variant === "women") overrides.sex = "female";
  if (variant === "body-fat") {
    overrides.bodyFatPercent = 18;
    overrides.formula = "katch-mcardle";
  }
  const ctx = useTDEEState(overrides);

  return (
    <div className={"calc" + (mobile ? " mobile" : "")}>
      <InputsPanel ctx={ctx} variant={variant} mobile={mobile} />
      <ResultsPanel ctx={ctx} variant={variant} />
    </div>
  );
}

// ─── Macros calculator (extension) ───────────────────────────────────────
function MacrosResultExtension({ tdee }) {
  const [preset, setPreset] = useStateC("standard");
  const split = window.TDEE.MACRO_PRESETS[preset];
  const macros = window.TDEE.calculateMacros({ dailyCalories: tdee, split });
  return (
    <div className="formula-explainer" style={{ marginTop: 32 }}>
      <div className="t-label" style={{ marginBottom: 12 }}>Macro split</div>
      <div className="macro-presets">
        {Object.entries(window.TDEE.MACRO_PRESETS).map(([k, v]) => (
          <button
            key={k}
            className={"macro-preset" + (preset === k ? " is-active" : "")}
            onClick={() => setPreset(k)}
          >
            {v.label}
          </button>
        ))}
      </div>
      <div style={{ marginTop: 14 }}>
        <MacroChart macros={macros} dailyCalories={tdee} />
      </div>
    </div>
  );
}

// ─── Body-fat compare ────────────────────────────────────────────────────
function BodyFatCompare({ inputs }) {
  if (!inputs.weightKg || inputs.bodyFatPercent == null) return null;
  const mifflin = window.TDEE.bmrMifflin({
    sex: inputs.sex, weightKg: inputs.weightKg, heightCm: inputs.heightCm, ageYears: inputs.age,
  });
  const katch = window.TDEE.bmrKatch({ weightKg: inputs.weightKg, bodyFatPercent: inputs.bodyFatPercent });
  const mult = window.TDEE.ACTIVITY_LEVELS[inputs.activityLevel].multiplier;
  const tM = Math.round(mifflin * mult);
  const tK = Math.round(katch * mult);
  const delta = tK - tM;

  return (
    <div className="bf-compare">
      <div className="bf-card">
        <div className="bf-card-label">
          <span className="t-label">Mifflin-St Jeor</span>
          <Chip>weight-based</Chip>
        </div>
        <div className="bf-card-val">{tM.toLocaleString()}</div>
        <div className="t-caption">Doesn't account for body composition</div>
      </div>
      <div className="bf-card is-recommended">
        <div className="bf-card-label">
          <span className="t-label">Katch-McArdle</span>
          <Chip tone="accent">recommended</Chip>
        </div>
        <div className="bf-card-val">{tK.toLocaleString()}</div>
        <div className="bf-delta">
          <span className={delta > 0 ? "bf-delta-up" : ""}>{delta > 0 ? "+" : ""}{delta}</span> calories vs Mifflin
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  TDEECalculator, useTDEEState, MacrosResultExtension, BodyFatCompare,
  InputsPanel, ResultsPanel,
});
