/* eslint-disable */
// app.jsx — wires Casa M landing page chrome to La Consola.
// Mounts: avatar chip, slide-out panel, View-As banner, Tweaks.

(function () {
  const { useState, useEffect, useMemo } = React;
  const V = window.CASAM_VIEWS;
  const { Consola } = window.CASAM_CONSOLA;
  const { TweaksPanel, TweakSection, TweakRadio, TweakSelect,
          TweakToggle, useTweaks } = window;

  // ─── tweakable defaults (persisted via __edit_mode_set_keys) ──
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "chrome": "right",
    "density": "comfortable",
    "tone": "bilingual",
    "familiasView": "list",
    "permisosView": "matrix",
    "demoAdmin": true,
    "showOpenCallout": true
  }/*EDITMODE-END*/;

  // ─── app root ─────────────────────────────────────────────
  function App() {
    const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
    const [open, setOpen] = useState(false);
    const [viewAs, setViewAs] = useState(null); // user id or null
    const [hint, setHint] = useState(false);

    const tone = tweaks.tone;
    const t = (es, en) => tone === "english" ? en : es;

    const seed = window.CASAM_CONSOLA_SEED;

    // "signed-in as" — the admin who's actually using the panel.
    // When viewAs is set, the avatar in the topbar shows the
    // impersonated user, but Consola still knows the real admin.
    const signedInAs = "mike";
    const displayedUser = useMemo(() => {
      const id = viewAs || signedInAs;
      return seed.users.find(u => u.id === id) || seed.users[0];
    }, [viewAs, seed]);

    const isAdmin = tweaks.demoAdmin;

    // Live clock
    useEffect(() => {
      function tick() {
        const now = new Date();
        const time = now.toLocaleTimeString("en-US", {
          hour: "numeric", minute: "2-digit", hour12: true,
        }).replace(/\u202f/g, " ");
        const [hm, ampm] = time.split(" ");
        const timeEl = document.getElementById("time");
        if (timeEl) timeEl.textContent = hm;
        const ampmEl = document.querySelector(".clock .ampm");
        if (ampmEl) ampmEl.textContent = ampm || "PM";
        // DEPRECATED — old hardcoded h<17 Spanish-only greeting + always-12h.
        // Replaced below with the sunset-anchored, language-aware version
        // per memory:casam_greeting_and_time_doctrine. This block is now
        // unreachable; left as a tombstone for the diff. New logic in
        // useEffect #2 (search: "DOCTRINE — see memory:").
      }
      // intentionally no tick() call — superseded effect renders instead
    }, [displayedUser]);

    // ─── Doctrine-correct clock + greeting ────────────────────────
    // Sunset-anchored, language-aware. EN-only → 12h; everything else 24h.
    // Visitor's local TZ drives sunset, NEVER the page-owner's city.
    useEffect(() => {
      const TZ_COORDS = {
        "America/Chicago":       [32.776, -96.797],
        "America/New_York":      [40.713, -74.006],
        "America/Los_Angeles":   [34.052,-118.244],
        "America/Denver":        [39.739,-104.985],
        "America/Phoenix":       [33.448,-112.074],
        "America/Anchorage":     [61.218,-149.900],
        "Pacific/Honolulu":      [21.307,-157.858],
        "America/Indiana/Indianapolis": [39.768, -86.158],
        "America/Detroit":       [42.331, -83.046],
        "America/Mexico_City":   [19.432, -99.133],
        "America/Monterrey":     [25.687,-100.317],
        "America/Tijuana":       [32.515,-117.038],
        "America/Cancun":        [21.161, -86.851],
        "Europe/London":         [51.507,  -0.128],
        "Europe/Amsterdam":      [52.367,   4.904],
        "Europe/Paris":          [48.857,   2.353],
        "Europe/Berlin":         [52.520,  13.405],
        "Europe/Rome":           [41.903,  12.496],
        "Europe/Madrid":         [40.417,  -3.704],
      };
      function visitorCoords(now) {
        try {
          const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
          if (tz && TZ_COORDS[tz]) return TZ_COORDS[tz];
        } catch {}
        const offMin = (now || new Date()).getTimezoneOffset();
        return [33.0, -(offMin / 60) * 15];
      }
      function sunsetFor(lat, lng, when) {
        const d = when instanceof Date ? when : new Date();
        const localOff = lng / 15;
        const local = new Date(d.getTime() + localOff * 3600 * 1000);
        const year  = local.getUTCFullYear();
        const month = local.getUTCMonth();
        const day   = local.getUTCDate();
        const start = Date.UTC(year, 0, 0);
        const doy = Math.floor((Date.UTC(year, month, day) - start) / 86400000);
        const rad = Math.PI / 180;
        const decl = 23.45 * Math.sin(rad * (360/365) * (doy - 81));
        const zen  = 90.833 * rad;
        const cosH = (Math.cos(zen) - Math.sin(lat*rad) * Math.sin(decl*rad))
                   / (Math.cos(lat*rad) * Math.cos(decl*rad));
        if (cosH > 1 || cosH < -1) return null;
        const H = Math.acos(cosH) / rad;
        const B = (360 / 365) * (doy - 81) * rad;
        const eot = 9.87 * Math.sin(2*B) - 7.53 * Math.cos(B) - 1.5 * Math.sin(B);
        const noonUTC   = 12 - lng / 15 - eot / 60;
        const sunsetUTC = noonUTC + H / 15;
        const result    = new Date(Date.UTC(year, month, day));
        return new Date(result.getTime() + Math.round(sunsetUTC * 3600 * 1000));
      }
      function timeOfDay(now, sunset) {
        const h = now.getHours();
        if (h < 4)  return "latenight";
        if (h < 12) return "morning";
        if (sunset && now >= sunset) {
          if (h >= 22) return "latenight";
          return "evening";
        }
        return "midday";
      }
      function getLang() {
        try {
          const v = localStorage.getItem("casam.lang");
          if (v === "en" || v === "es" || v === "en-es") return v;
        } catch {}
        return "en-es";
      }
      const GREETINGS = {
        en: {
          morning:   ["Good morning",    "Buenos días"],
          midday:    ["Good afternoon",  "Buenas tardes"],
          evening:   ["Good evening",    "Buenas noches"],
          latenight: ["A late one",      "Buenas trasnoche"],
        },
        es: {
          morning:   ["Buenos días",     "Good morning"],
          midday:    ["Buenas tardes",   "Good afternoon"],
          evening:   ["Buenas noches",   "Good evening"],
          latenight: ["Buenas trasnoche","A late one"],
        },
      };
      function tzAbbrev(now) {
        try {
          const parts = new Intl.DateTimeFormat("en-US", { timeZoneName: "short" })
            .formatToParts(now);
          const tz = parts.find((p) => p.type === "timeZoneName");
          return tz ? tz.value : "";
        } catch { return ""; }
      }
      function tick() {
        const now = new Date();
        const lang = getLang();
        const use12h = lang === "en";

        const hh24 = now.getHours();
        const mm   = String(now.getMinutes()).padStart(2, "0");
        const timeEl = document.getElementById("time");
        const ampmEl = document.querySelector(".clock .ampm");
        if (use12h) {
          const h12 = ((hh24 + 11) % 12) + 1;
          if (timeEl) timeEl.textContent = `${h12}:${mm}`;
          if (ampmEl) {
            ampmEl.textContent = hh24 < 12 ? "AM" : "PM";
            ampmEl.style.display = "";
          }
        } else {
          if (timeEl) timeEl.textContent = `${String(hh24).padStart(2, "0")}:${mm}`;
          if (ampmEl) ampmEl.style.display = "none";
        }

        const tzEl = document.getElementById("tz");
        if (tzEl) tzEl.textContent = tzAbbrev(now);

        const [vLat, vLng] = visitorCoords(now);
        const sunset = sunsetFor(vLat, vLng, now);
        const bucket = timeOfDay(now, sunset);

        const primaryLang   = (lang === "en") ? "en" : "es";
        const secondaryLang = (lang === "en-es") ? "en" : null;
        const [primary] = GREETINGS[primaryLang][bucket];
        const firstName = displayedUser.name.split(" ")[0];

        const greetEl = document.getElementById("greeting");
        if (greetEl) {
          const main = `${primary}, ${firstName}.`;
          if (secondaryLang) {
            const sec = GREETINGS[secondaryLang][bucket][0];
            greetEl.innerHTML =
              `${main} <em style="opacity:0.55;font-style:italic;">${sec}, ${firstName}.</em>`;
          } else {
            greetEl.textContent = main;
          }
        }
        const subEl = document.getElementById("greeting-sub");
        if (subEl) {
          subEl.textContent = (lang === "en")
            ? "Casa M — the house dashboard."
            : "Casa M — el panel de la casa.";
        }
      }
      function wirePicker() {
        const picker = document.getElementById("lang-picker");
        if (!picker) return;
        const cur = getLang();
        picker.querySelectorAll("button[data-lang]").forEach((b) => {
          b.classList.toggle("on", b.dataset.lang === cur);
          b.onclick = () => {
            try { localStorage.setItem("casam.lang", b.dataset.lang); } catch {}
            picker.querySelectorAll("button[data-lang]").forEach((x) =>
              x.classList.toggle("on", x.dataset.lang === b.dataset.lang));
            tick();
          };
        });
      }
      wirePicker();
      tick();
      const id = setInterval(tick, 30 * 1000);
      return () => clearInterval(id);
    }, [displayedUser]);

    // Body class for view-as mode
    useEffect(() => {
      if (viewAs) document.body.classList.add("is-view-as");
      else document.body.classList.remove("is-view-as");
      return () => document.body.classList.remove("is-view-as");
    }, [viewAs]);

    // Hint pulse on first paint (1s after load) — only first visit
    useEffect(() => {
      if (!isAdmin || !tweaks.showOpenCallout) return;
      const dismissed = localStorage.getItem("casam-consola-hint-seen");
      if (dismissed) return;
      const id = setTimeout(() => setHint(true), 900);
      return () => clearTimeout(id);
    }, [isAdmin, tweaks.showOpenCallout]);

    function openConsola() {
      setOpen(true);
      setHint(false);
      localStorage.setItem("casam-consola-hint-seen", "1");
    }

    return (
      <React.Fragment>
        <AvatarChipPortal user={displayedUser} isAdmin={isAdmin && !viewAs}
          onClick={isAdmin ? openConsola : () => {}} hint={hint} />

        <Consola
          open={open} onClose={() => setOpen(false)}
          density={tweaks.density}
          tone={tone}
          chrome={tweaks.chrome}
          familiasView={tweaks.familiasView}
          permisosView={tweaks.permisosView}
          viewAs={viewAs}
          setViewAs={setViewAs}
          signedInAs={signedInAs} />

        <ViewAsBannerPortal viewAs={viewAs} state={seed}
          signedInAs={signedInAs}
          onExit={() => setViewAs(null)} />

        <TweaksUI tweaks={tweaks} setTweak={setTweak}
          onOpenConsola={openConsola}
          isAdmin={isAdmin}
          viewAs={viewAs} />
      </React.Fragment>
    );
  }

  // ─── Avatar chip — rendered into the topbar mount ────────
  function AvatarChipPortal({ user, isAdmin, onClick, hint }) {
    const mount = document.getElementById("me-chip-mount");
    if (!mount) return null;
    return ReactDOM.createPortal(
      <div onClick={onClick} className="me-chip"
        data-admin={isAdmin ? "true" : "false"}
        title={isAdmin ? "Open La Consola" : `Signed in as ${user.name}`}
        style={{ cursor: isAdmin ? "pointer" : "default" }}>
        <div className="me-text">
          <span className="me-name">{user.name.split(" ")[0]}</span>
          <span className="me-loc">
            {isAdmin ? "Admin · La Consola" : (user.city || "—")}
          </span>
        </div>
        <span className="dot" style={{ background: user.accent }}>
          {user.name.split(" ").map(s => s[0]).slice(0,2).join("")}
        </span>
        {hint && (
          <span style={{
            position: "absolute", top: "100%", right: 0, marginTop: 12,
            padding: "9px 14px",
            background: "var(--gold)", color: "var(--bg)",
            borderRadius: 6, whiteSpace: "nowrap",
            fontFamily: "var(--sans)", fontSize: 10.5, letterSpacing: 1.6,
            fontWeight: 700, textTransform: "uppercase",
            boxShadow: "0 12px 28px rgba(0,0,0,0.4)",
            animation: "consola-hint 2s ease-in-out infinite",
            pointerEvents: "none", zIndex: 50,
          }}>
            <span style={{
              position: "absolute", top: -6, right: 24,
              width: 12, height: 12, background: "var(--gold)",
              transform: "rotate(45deg)",
            }} />
            ↑ Click for La Consola
          </span>
        )}
        <style>{`
          @keyframes consola-hint {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-3px); }
          }
        `}</style>
      </div>,
      mount
    );
  }

  // ─── View-as banner — rendered into top of body ──────────
  function ViewAsBannerPortal({ viewAs, state, signedInAs, onExit }) {
    const mount = document.getElementById("view-as-mount");
    if (!mount || !viewAs) return null;
    const target = state.users.find(u => u.id === viewAs);
    const me = state.users.find(u => u.id === signedInAs);
    if (!target) return null;
    return ReactDOM.createPortal(
      <div className="view-as-banner">
        <span className="eye">◉</span>
        <span style={{
          fontFamily: "var(--sans)", fontSize: 9.5, letterSpacing: 2.4,
        }}>View as</span>
        <span className="who">
          {target.name}
          {target.familyId && (() => {
            const f = state.families.find(x => x.id === target.familyId);
            return f ? <b style={{ marginLeft: 8 }}>· {f.name}</b> : null;
          })()}
        </span>
        <span className="ro-pill">READ-ONLY</span>
        <span style={{
          fontFamily: "var(--serif)", fontStyle: "italic",
          color: "#FFE6CF", fontSize: 13, letterSpacing: 0, textTransform: "none",
          fontWeight: 400,
        }}>
          · really {me.name.split(" ")[0]}, impersonating
        </span>
        <button className="exit" onClick={onExit}>← Exit view-as</button>
      </div>,
      mount
    );
  }

  // ─── Tweaks panel ────────────────────────────────────────
  function TweaksUI({ tweaks, setTweak, onOpenConsola, isAdmin, viewAs }) {
    return (
      <TweaksPanel
        title="Tweaks"
        intro="Variations for La Consola. Toggle demoAdmin off to see the non-admin path."
      >
        <TweakSection label="Show the panel" />
        <div style={{ padding: "0 14px 8px" }}>
          <button onClick={onOpenConsola} disabled={!isAdmin || !!viewAs} style={{
            padding: "10px 14px", borderRadius: 4,
            background: isAdmin && !viewAs ? "#D4B07A" : "rgba(212,176,122,0.20)",
            color: isAdmin && !viewAs ? "#1A120C" : "rgba(241,230,208,0.5)",
            border: "1px solid #A87B2C", cursor: isAdmin && !viewAs ? "pointer" : "not-allowed",
            fontFamily: "'Manrope', sans-serif", fontSize: 10.5, letterSpacing: 1.8,
            fontWeight: 700, textTransform: "uppercase", width: "100%",
          }}>
            {viewAs ? "Exit view-as first" : "Open La Consola →"}
          </button>
        </div>
        <TweakToggle label="Treat me as a site admin"
          value={tweaks.demoAdmin}
          onChange={(v) => setTweak("demoAdmin", v)} />
        <TweakToggle label="First-visit callout"
          value={tweaks.showOpenCallout}
          onChange={(v) => setTweak("showOpenCallout", v)} />

        <TweakSection label="Panel chrome" />
        <TweakRadio label="From"
          value={tweaks.chrome}
          options={[
            { value: "right", label: "Right" },
            { value: "sheet", label: "Sheet" },
            { value: "floating", label: "Center" },
          ]}
          onChange={(v) => setTweak("chrome", v)} />

        <TweakSection label="Density" />
        <TweakRadio label="Rows"
          value={tweaks.density}
          options={[
            { value: "comfortable", label: "Comfy" },
            { value: "compact", label: "Compact" },
          ]}
          onChange={(v) => setTweak("density", v)} />

        <TweakSection label="Tone" />
        <TweakRadio label="Copy"
          value={tweaks.tone}
          options={[
            { value: "bilingual", label: "ES + EN" },
            { value: "english", label: "EN only" },
          ]}
          onChange={(v) => setTweak("tone", v)} />
      </TweaksPanel>
    );
  }

  // ─── mount ────────────────────────────────────────────────
  const root = ReactDOM.createRoot(document.getElementById("consola-mount"));
  root.render(<App />);
})();
