/* eslint-disable */
// ===========================================================================
// Omnivore UI — shared components (nutrition table, sheets, metric row)
//
// Part of the in-browser (no-build) React app. These files are loaded in order
// as separate <script type="text/babel"> tags (see index.html); Babel compiles
// each as a classic global script, so top-level names declared in earlier files
// are visible here. Depends on ui/base.jsx.
// ===========================================================================

// ── tiny Markdown renderer (coach replies) ─────────────────────────────────
// The coach is an LLM and answers in light Markdown — **bold**, *italics*,
// `code`, "* " / "- " bullet lists and #/##/### headings. React prints strings
// verbatim, so without this the user just sees literal **stars** and stray "* "
// markers. We parse a small, fixed subset into React elements: no HTML string is
// ever built, so a coach reply can't inject markup (no dangerouslySetInnerHTML).

// Inline pass: turn one line of text into an array of strings + <strong>/<em>/
// <code> nodes. Bold is tried before italics (it's listed first in the regex, so
// "**" wins over "*" at the same spot). The non-space lookahead after a marker
// (e.g. `\*[^\s*]`) keeps a stray "2 * 3" or a bullet's "* " from italicising.
function mdInline(text, kp) {
  const re = /\*\*([^\s][\s\S]*?)\*\*|\*([^\s*][\s\S]*?)\*|_([^\s_][\s\S]*?)_|`([^`]+?)`/g;
  const nodes = [];
  let last = 0, m, i = 0;
  while ((m = re.exec(text)) !== null) {
    if (m.index > last) nodes.push(text.slice(last, m.index));
    if (m[1] != null) nodes.push(<strong key={kp + "b" + i} style={{ fontWeight: 600 }}>{m[1]}</strong>);
    else if (m[2] != null || m[3] != null) nodes.push(<em key={kp + "i" + i}>{m[2] != null ? m[2] : m[3]}</em>);
    else nodes.push(
      <code key={kp + "c" + i} style={{ background: C.bg, border: `1px solid ${C.line}`,
        borderRadius: 4, padding: "0 4px", fontSize: "0.92em" }}>{m[4]}</code>);
    last = re.lastIndex; i++;
  }
  if (last < text.length) nodes.push(text.slice(last));
  return nodes;
}

// Block pass: group lines into bullet lists, headings and paragraphs, then map
// each block to an element (inline-parsing its text). Blank lines separate blocks.
function Markdown({ text, style }) {
  const blocks = [];
  let list = null;
  const closeList = () => { if (list) { blocks.push({ t: "ul", items: list }); list = null; } };
  String(text == null ? "" : text).replace(/\r\n?/g, "\n").split("\n").forEach((raw) => {
    const line = raw.replace(/\s+$/, "");
    const bullet = /^\s*[-*•]\s+(.*)$/.exec(line);
    if (bullet) { (list || (list = [])).push(bullet[1]); return; }
    closeList();
    const head = /^\s*(#{1,3})\s+(.*)$/.exec(line);
    if (head) blocks.push({ t: "h", level: head[1].length, text: head[2] });
    else if (line.trim() === "") blocks.push({ t: "sp" });
    else blocks.push({ t: "p", text: line });
  });
  closeList();
  while (blocks.length && blocks[0].t === "sp") blocks.shift();
  while (blocks.length && blocks[blocks.length - 1].t === "sp") blocks.pop();

  return (
    <div style={style}>
      {blocks.map((b, i) => {
        if (b.t === "sp") return <div key={i} style={{ height: 6 }} />;
        if (b.t === "ul")
          return (
            <ul key={i} style={{ margin: "4px 0", paddingLeft: 18 }}>
              {b.items.map((it, j) => <li key={j} style={{ margin: "2px 0" }}>{mdInline(it, i + "-" + j + "-")}</li>)}
            </ul>
          );
        if (b.t === "h")
          return (
            <div key={i} style={{ fontWeight: 600, fontSize: b.level === 1 ? "1.12em" : "1em", margin: "6px 0 2px" }}>
              {mdInline(b.text, "h" + i + "-")}
            </div>
          );
        return <p key={i} style={{ margin: "4px 0" }}>{mdInline(b.text, "p" + i + "-")}</p>;
      })}
    </div>
  );
}

// ── nutrition breakdown (shared by Result + Recap meal detail) ──────────────
const NUTRIENTS = [
  ["calories", "Calories", 0], ["fat", "Total fat", 0], ["saturated_fat", "Saturated fat", 1],
  ["carbs", "Total carbohydrate", 0], ["fiber", "Dietary fiber", 1],
  ["sugar", "Total sugars", 1], ["added_sugar", "Added sugars", 2], ["protein", "Protein", 0],
];

function NutrientValue({ n }) {
  if (!n || !n.known || n.amount == null) return <span style={{ color: C.faint }}>unknown</span>;
  return (
    <span>
      {fmt(n.amount)} {n.unit || ""}
      {n.estimated && <span style={{ color: C.faint }}> ~</span>}
      {n.partial && <span style={{ color: C.faint }}> *</span>}
    </span>
  );
}
function NutrientTable({ nutrients }) {
  return (
    <table style={{ width: "100%", fontSize: 13, borderCollapse: "collapse" }}>
      <tbody>
        {NUTRIENTS.map(([k, label, indent]) => (
          <tr key={k} style={{ borderBottom: `1px solid ${C.line}` }}>
            <td style={{ padding: "6px 0", color: C.dim, paddingLeft: indent === 1 ? 16 : indent === 2 ? 32 : 0 }}>{label}</td>
            <td style={{ padding: "6px 0", textAlign: "right", color: C.text }}><NutrientValue n={nutrients[k]} /></td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}
function ClassTags({ cls }) {
  if (!cls) return null;
  const tags = [];
  if (cls.plant_category && cls.plant_category !== "none") tags.push(cls.plant_category.replace("_", " "));
  if (cls.nova_group === 4) tags.push("ultra-processed");
  if (!tags.length) return null;
  return (
    <span style={{ marginLeft: 6 }}>
      {tags.map((t) => (
        <span key={t} style={{ display: "inline-block", padding: "1px 6px", borderRadius: 6, background: C.bg,
          border: `1px solid ${C.line}`, fontSize: 10, color: C.dim, marginRight: 4 }}>{t}</span>
      ))}
    </span>
  );
}
function MealDetail({ meal }) {
  const comps = meal.components || [];
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
      {comps.length > 0 && (
        <div>
          {comps.map((c, i) => {
            const q = c.quantity || {};
            const amt = q.grams ? `${fmt(q.grams)} g` : q.serving || `×${q.count || 1}`;
            return (
              <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "center",
                borderBottom: `1px solid ${C.line}`, padding: "8px 0", fontSize: 14 }}>
                <span style={{ color: C.text }}>{c.name}<ClassTags cls={c.classification} /></span>
                <span style={{ color: C.faint, whiteSpace: "nowrap" }}>{amt}</span>
              </div>
            );
          })}
        </div>
      )}
      <div>
        <div style={{ fontSize: 12, color: C.faint, marginBottom: 4 }}>Nutrition facts</div>
        <NutrientTable nutrients={meal.nutrients || {}} />
      </div>
    </div>
  );
}

// ── info bottom sheet (metric explanation) ──────────────────────────────────
function InfoSheet({ item, onClose }) {
  const drag = useDragToClose(onClose);
  if (!item) return null;
  return (
    <div onClick={onClose} style={{ position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)",
      display: "flex", alignItems: "flex-end", zIndex: 60 }}>
      <div onClick={(e) => e.stopPropagation()} {...drag.handlers} style={{ width: "100%", background: C.card,
        borderRadius: "18px 18px 0 0", padding: "18px 22px 32px", touchAction: "none", ...drag.style }}>
        <div style={{ width: 36, height: 4, background: C.line, borderRadius: 2, margin: "0 auto 16px" }} />
        <div style={{ fontSize: 16, fontWeight: 600, color: C.text, marginBottom: 8 }}>{item.label}</div>
        <div style={{ fontSize: 14, color: C.dim, lineHeight: 1.55 }}>{metricInfo(item)}</div>
      </div>
    </div>
  );
}

// ── install instructions bottom sheet (manual / iOS / non-secure fallback) ──
function InstallSheet({ open, onClose }) {
  const drag = useDragToClose(onClose);
  if (!open) return null;
  let steps;
  if (IS_IOS)
    steps = [
      "Make sure you opened this page in Safari.",
      "Tap the Share button (the square with an up-arrow).",
      "Scroll down and choose “Add to Home Screen”, then “Add”.",
    ];
  else if (IS_ANDROID)
    steps = [
      "Open the browser menu (⋮ in the top-right).",
      "Tap “Install app” or “Add to Home screen”.",
      "Confirm to add Omnivore to your home screen.",
    ];
  else
    steps = [
      "Open your browser’s menu, or the install icon in the address bar.",
      "Choose “Install Omnivore”.",
    ];
  const insecure = typeof window !== "undefined" && !window.isSecureContext;

  return (
    <div onClick={onClose} style={{ position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)",
      display: "flex", alignItems: "flex-end", zIndex: 60 }}>
      <div onClick={(e) => e.stopPropagation()} {...drag.handlers} style={{ width: "100%", background: C.card,
        borderRadius: "18px 18px 0 0", padding: "18px 22px 32px", touchAction: "none", ...drag.style }}>
        <div style={{ width: 36, height: 4, background: C.line, borderRadius: 2, margin: "0 auto 16px" }} />
        <div style={{ fontSize: 16, fontWeight: 600, color: C.text, marginBottom: 12 }}>Install Omnivore</div>
        <ol style={{ margin: 0, paddingLeft: 20, color: C.dim, fontSize: 14, lineHeight: 1.7 }}>
          {steps.map((s, i) => <li key={i}>{s}</li>)}
        </ol>
        {insecure && (
          <div style={{ marginTop: 14, fontSize: 13, color: C.over, lineHeight: 1.5 }}>
            {IS_IOS
              ? "Heads up: the camera needs an https:// address to work inside the installed app."
              : "On Android the one-tap install only appears over an https:// address — open the app over HTTPS, not http://."}
          </div>
        )}
      </div>
    </div>
  );
}

// ── a single tappable metric row (tap = reveal detail) ──────────────────────
function MetricRow({ m, onInfo }) {
  const [open, setOpen] = useState(false);
  const tier = metricTier(m);
  return (
    <div style={{ borderBottom: `1px solid ${C.line}` }}>
      <div onClick={() => setOpen(!open)}
        style={{ display: "flex", alignItems: "center", gap: 12, padding: "15px 4px", cursor: "pointer" }}>
        <span style={{ width: 8, height: 8, borderRadius: 4, background: dot(tier), flexShrink: 0 }} />
        <span style={{ flex: 1, fontSize: 15, color: C.text }}>{m.label}</span>
        <span style={{ fontSize: 13, color: C.dim }}>{metricValue(m)}</span>
      </div>
      {open && (
        <div style={{ padding: "0 4px 14px 32px", display: "flex", alignItems: "center", gap: 10 }}>
          <span style={{ fontSize: 13, color: C.faint, flex: 1 }}>{metricInfo(m).split(".")[0]}.</span>
          <button onClick={(e) => { e.stopPropagation(); onInfo(m); }}
            style={{ background: "none", border: `1px solid ${C.line}`, color: C.dim, borderRadius: 16,
              width: 26, height: 26, fontSize: 13, cursor: "pointer", flexShrink: 0 }}>ⓘ</button>
        </div>
      )}
    </div>
  );
}
