// RecordCard — the atomic object the entire product inherits from.
//
// Three trust axes, never collapsed. Aligned with the Grain protocol:
//
//   1. trust_status  (record trust)    verified | self-issued | untrusted
//      → who signed the file: an issuer, your device, or nobody we can name
//
//   2. integrity     (bytes)           unchanged | modified | cannot-verify
//      → are the bytes the same as the issued copy
//
//   3. source_class  (number confidence)  attested | measured | estimated | unknown
//      → how the kcal number got onto the record. Lives NEXT TO the number,
//        because it qualifies the data, not the file.
//
// CRITICAL semantics:
//   - Only kcal is normatively verified by the protocol. P/C/F are app-entered
//     and live in a SEPARATE visual tier with an explicit "app-entered" label.
//     A verified record is verified about kcal, not about macros.
//   - Confidence is shown as a real ± range (kcal ± var), not just a label.
//     Attested ≈ ±2–9. Measured ≈ ±9–20. Estimated ≈ ±60–150. Unknown = no ±.
//   - "verified" means authentic + intact, NOT that the calories are true.
//   - Untrusted records open in a calm safe-read-only state (grey, lock, no teal).

const IconCheck = ({ size = 14 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
    <path d="M4 12.5l5 5L20 6.5" />
  </svg>
);
const IconLock = ({ size = 14 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <rect x="5" y="11" width="14" height="9" rx="2" />
    <path d="M8 11V8a4 4 0 0 1 8 0v3" />
  </svg>
);
const IconAlertTri = ({ size = 14 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M12 4 L21 19 H3 Z" />
    <path d="M12 10v4" />
    <circle cx="12" cy="17" r="0.6" fill="currentColor" stroke="none" />
  </svg>
);
const IconScale = ({ size = 14 }) => (
  // Kitchen scale glyph — distinct mark for the "measured" state.
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
    <path d="M5 18h14" />
    <rect x="7" y="14" width="10" height="4" rx="1" />
    <path d="M9 14V8h6v6" />
    <path d="M12 8V5" />
  </svg>
);
const IconChevron = ({ size = 14, dir = "down" }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"
       style={{ transform: dir === "up" ? "rotate(180deg)" : "none", transition: "transform 200ms ease" }}>
    <path d="M6 9l6 6 6-6" />
  </svg>
);
const IconHash = ({ size = 12 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M5 9h14M5 15h14M10 4l-2 16M16 4l-2 16" />
  </svg>
);
const IconFile = ({ size = 14 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
    <path d="M7 3h7l4 4v14H7z" />
    <path d="M14 3v4h4" />
  </svg>
);
const IconDownload = ({ size = 14 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
    <path d="M12 4v12" />
    <path d="M6 12l6 5 6-5" />
    <path d="M5 20h14" />
  </svg>
);
const IconQR = ({ size = 14 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="none"
       stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
    <rect x="3" y="3" width="7" height="7" rx="0.6" />
    <rect x="14" y="3" width="7" height="7" rx="0.6" />
    <rect x="3" y="14" width="7" height="7" rx="0.6" />
    <path d="M14 14h3v3h-3zM20 14v3M14 20h3M20 20h1" />
  </svg>
);

// --- State dictionaries ---------------------------------------------------

const RECORD_TRUST = {
  verified:     { label: "Verified",    tone: "teal",  pillIcon: <IconCheck />, sub: "Comes from the brand" },
  "self-issued":{ label: "Saved by you", tone: "ghost", pillIcon: null,          sub: "Saved on your iPhone" },
  untrusted:    { label: "Read-only",   tone: "grey",  pillIcon: <IconLock />,  sub: "We can't confirm where it came from" },
};

const INTEGRITY = {
  unchanged:        { label: "Unchanged",     tone: "teal",  pillIcon: <IconCheck />,    sub: "Same as when it was saved" },
  modified:         { label: "Edited",        tone: "amber", pillIcon: <IconAlertTri />, sub: "Edits are shown, never hidden" },
  "cannot-verify":  { label: "Cannot check",  tone: "grey",  pillIcon: <IconLock />,     sub: "We can't check this right now" },
};

// source_class — user-facing labels for how the kcal got onto the record.
const SOURCE_CLASS = {
  attested:  { label: "Brand",     tone: "teal",  icon: <IconCheck size={11} />,    note: "From the brand\u2019s own menu data" },
  measured:  { label: "Weighed",   tone: "teal",  icon: <IconScale size={11} />,    note: "You weighed it during capture" },
  estimated: { label: "Estimated", tone: "amber", icon: <IconAlertTri size={11} />, note: "Guessed from a photo or quick entry" },
  unknown:   { label: "No claim",  tone: "grey",  icon: null,                       note: "We make no claim about this number" },
};

function pillClass(tone) {
  return {
    teal: "pill pill-teal",
    amber: "pill pill-amber",
    grey: "pill pill-grey",
    ghost: "pill pill-ghost",
  }[tone] || "pill pill-ghost";
}

// Safe-read-only: anywhere we can't show trust, the record goes neutral grey.
function isSafeReadOnly(recordTrust, integrity) {
  return recordTrust === "untrusted" || integrity === "cannot-verify";
}

// --- The card ------------------------------------------------------------

function RecordCard({
  meal,
  date,
  source,                // override the auto sub for the source line
  issuer,                // explicit issuer name (e.g. "Demo Café") shown next to Attested
  calories,
  varKcal,               // ± kcal — required for attested/measured/estimated, omitted for unknown
  macros,                // { p, c, f } in grams — always app-entered, never verified
  recordTrust = "self-issued",
  integrity = "unchanged",
  sourceClass = "measured",
  imageUrl,
  imageAlt = "",
  size = "default",      // "default" | "compact"
  showTechnical = false,
  compactProvenance = false,
}) {
  const [techOpen, setTechOpen] = React.useState(showTechnical);
  const safe = isSafeReadOnly(recordTrust, integrity);
  const trust = RECORD_TRUST[recordTrust];
  const integ = INTEGRITY[integrity];
  const cls = SOURCE_CLASS[sourceClass];

  // Verified seal only shows when BOTH file authenticity (verified) AND
  // bytes (unchanged) hold. The seal is about the file, not the numbers.
  const showSeal = recordTrust === "verified" && integrity === "unchanged";

  // No ± shown for unknown / safe-read-only — we explicitly make no claim.
  const showRange = !safe && sourceClass !== "unknown" && typeof varKcal === "number";

  const compact = size === "compact";

  return (
    <article
      className="record-card"
      data-trust={recordTrust}
      data-integrity={integrity}
      data-source-class={sourceClass}
      data-safe={safe ? "true" : "false"}
      aria-label={`Meal record: ${meal}, ${calories} kcal, ${cls.label.toLowerCase()}`}
    >
      {/* Photo */}
      <div className={"record-photo" + (safe ? " untrusted-grey" : "")}>
        {imageUrl ? (
          <img src={imageUrl} alt={imageAlt} loading="lazy" />
        ) : (
          <div className="record-photo-ph" aria-hidden="true">
            <span className="mono">meal photo</span>
          </div>
        )}
        {showSeal && (
          <div className="record-seal" title="Verified record · bytes unchanged">
            <span className="seal seal-lg" aria-hidden="true"><IconCheck size={16} /></span>
          </div>
        )}
        {safe && (
          <div className="record-safe-banner" role="status">
            <IconLock size={13} />
            <span>Read-only · source unverified</span>
          </div>
        )}
      </div>

      {/* Body */}
      <div className="record-body">
        <div className="record-meta">
          <span className="label">Meal record</span>
          <span className="record-meta-dot" aria-hidden="true">·</span>
          <span className="label">{date}</span>
        </div>

        <h3 className={compact ? "h-card" : "h-meal"}>{meal}</h3>

        {/* The kcal number is the verifiable quantity. Confidence sits inline
            as a real ± range, then a small source_class pill explains what
            kind of confidence it is. */}
        <div className="record-kcal">
          <div className="record-kcal-num-wrap">
            <span className="record-cal-num">{calories.toLocaleString()}</span>
            {showRange && (
              <span className="record-cal-pm" aria-label={`plus or minus ${varKcal} kcal`}>
                <span className="record-cal-pm-sym">±</span>
                <span className="record-cal-pm-v">{varKcal}</span>
              </span>
            )}
            <span className="record-cal-unit">kcal</span>
          </div>
          <span className={pillClass(cls.tone) + " record-cls-pill"} title={cls.note}>
            {cls.icon && <span className="pill-icon">{cls.icon}</span>}
            {cls.label}
            {issuer && sourceClass === "attested" && (
              <span className="record-cls-issuer">· {issuer}</span>
            )}
          </span>
        </div>

        {/* Macros — separate tier. App-entered, NOT verified by the protocol. */}
        <div className="record-macros">
          <div className="record-macros-head">
            <span className="record-macros-label">Macros</span>
            <span className="record-macros-tag">app-entered</span>
          </div>
          <div className="record-macros-row">
            <Macro letter="P" g={macros.p} />
            <Macro letter="C" g={macros.c} />
            <Macro letter="F" g={macros.f} />
          </div>
        </div>

        <div className="rule" style={{ margin: "18px 0 14px" }} />

        {/* Provenance — two file-level axes. Never the same axis as source_class. */}
        <div className={"record-prov" + (compactProvenance ? " compact" : "")}>
          <ProvRow
            label="Source"
            chip={
              <span className={pillClass(trust.tone)}>
                {trust.pillIcon && <span className="pill-icon">{trust.pillIcon}</span>}
                {trust.label}
              </span>
            }
            sub={source || trust.sub}
          />
          <ProvRow
            label="State"
            chip={
              <span className={pillClass(integ.tone)}>
                {integ.pillIcon && <span className="pill-icon">{integ.pillIcon}</span>}
                {integ.label}
              </span>
            }
            sub={integ.sub}
          />
        </div>

        {/* Technical details — hidden by default. Normal users never see a hash. */}
        <button
          type="button"
          className="record-tech-toggle"
          aria-expanded={techOpen}
          onClick={() => setTechOpen(o => !o)}
        >
          <IconHash />
          <span>Technical details</span>
          <span className="record-tech-chev" aria-hidden="true">
            <IconChevron dir={techOpen ? "up" : "down"} />
          </span>
        </button>

        {techOpen && (
          <div className="record-tech">
            <TechRow k="Format" v="meal/1.0 · COSE-signed" />
            <TechRow k="CID" v={<span className="mono">bafyrei…h7q4m2</span>} />
            <TechRow k="Issued" v="May 26, 2026 · 09:14:33 UTC" />
            <TechRow
              k="Signer key"
              v={<span className="mono">{recordTrust === "verified" ? "ed25519 d-cafe…7a31" : "ed25519 device…8f4a"}</span>}
            />
            <TechRow k="kcal model" v={<span className="mono">μ={calories} · var={varKcal ?? "—"}</span>} />
          </div>
        )}
      </div>
    </article>
  );
}

function Macro({ letter, g }) {
  return (
    <div className="macro">
      <span className="macro-letter">{letter}</span>
      <span className="macro-g">{g}<span className="macro-unit">g</span></span>
    </div>
  );
}

function ProvRow({ label, chip, sub }) {
  return (
    <div className="prov-row">
      <span className="prov-label">{label}</span>
      <div className="prov-value">
        {chip}
        {sub && <span className="prov-sub">{sub}</span>}
      </div>
    </div>
  );
}

function TechRow({ k, v }) {
  return (
    <div className="tech-row">
      <span className="tech-k">{k}</span>
      <span className="tech-v">{v}</span>
    </div>
  );
}

Object.assign(window, {
  RecordCard,
  IconCheck, IconLock, IconAlertTri, IconScale, IconChevron, IconHash,
  IconFile, IconDownload, IconQR,
  isSafeReadOnly,
  SOURCE_CLASS, RECORD_TRUST, INTEGRITY,
});
