/* =========================================================
   home.jsx — "Your office is handling it." home screen

   Polish wave 1 (COO-19/20/21/22/24):
   - SVG crew avatars + house thumbnails
   - Denser waveform + smarter voice selection
   - Per-kind attention modals + exit animation
   - Stats row + AllGood + project tile refinements
   ========================================================= */

/* =========================================================
   CREW AVATARS — inline SVG, one per crew.id
   Notion-leaning portraits, warm color palette,
   robot face for the Takeoff Reader.
   ========================================================= */

const AvatarBookkeeper = () => (
  <svg viewBox="0 0 56 56" width="100%" height="100%" aria-hidden="true">
    <circle cx="28" cy="28" r="28" fill="#F4D8B0" />
    {/* hair */}
    <path d="M11 28 C11 17 18 11 28 11 C38 11 45 17 45 28 L45 32 C45 30 42 28 39 28 L17 28 C14 28 11 30 11 32 Z" fill="#3E2A1E" />
    {/* face */}
    <ellipse cx="28" cy="30" rx="13" ry="14" fill="#F1C9A5" />
    {/* glasses */}
    <circle cx="22" cy="29" r="3.2" fill="none" stroke="#2A2018" strokeWidth="1.2" />
    <circle cx="34" cy="29" r="3.2" fill="none" stroke="#2A2018" strokeWidth="1.2" />
    <path d="M25.2 29 L30.8 29" stroke="#2A2018" strokeWidth="1.2" strokeLinecap="round" />
    {/* eyes */}
    <circle cx="22" cy="29" r="1" fill="#2A2018" />
    <circle cx="34" cy="29" r="1" fill="#2A2018" />
    {/* smile */}
    <path d="M24 37 Q28 39.5 32 37" stroke="#7A4A2E" strokeWidth="1.2" fill="none" strokeLinecap="round" />
    {/* collar */}
    <path d="M16 50 C18 44 23 42 28 42 C33 42 38 44 40 50 Z" fill="#2E4E7C" />
    <path d="M28 42 L25 48 L28 50 L31 48 Z" fill="#FFFFFF" />
  </svg>
);

const AvatarField = () => (
  <svg viewBox="0 0 56 56" width="100%" height="100%" aria-hidden="true">
    <circle cx="28" cy="28" r="28" fill="#FFD6A8" />
    {/* hard hat */}
    <path d="M13 25 C13 19 19 14 28 14 C37 14 43 19 43 25 L43 27 L13 27 Z" fill="#E8861F" />
    <rect x="12" y="26" width="32" height="2.4" rx="1.2" fill="#B5530C" />
    <rect x="26.5" y="14.5" width="3" height="6" fill="#B5530C" />
    {/* face */}
    <ellipse cx="28" cy="32" rx="11" ry="12" fill="#E8B98C" />
    {/* eyes */}
    <circle cx="23.5" cy="31" r="1.1" fill="#2A2018" />
    <circle cx="32.5" cy="31" r="1.1" fill="#2A2018" />
    {/* beard line */}
    <path d="M20 36 C22 41 25 43 28 43 C31 43 34 41 36 36" fill="none" stroke="#5B3A24" strokeWidth="1.1" strokeLinecap="round" />
    {/* smile */}
    <path d="M25 38 Q28 40 31 38" stroke="#5B3A24" strokeWidth="1.2" fill="none" strokeLinecap="round" />
    {/* vest */}
    <path d="M14 52 C16 46 21 43 28 43 C35 43 40 46 42 52 Z" fill="#F2A93B" />
    <path d="M22 45 L22 52 M34 45 L34 52" stroke="#FFFFFF" strokeWidth="1.2" strokeLinecap="round" />
  </svg>
);

const AvatarClient = () => (
  <svg viewBox="0 0 56 56" width="100%" height="100%" aria-hidden="true">
    <circle cx="28" cy="28" r="28" fill="#F7D9D2" />
    {/* hair bun + sides */}
    <ellipse cx="28" cy="12" rx="5" ry="3.5" fill="#3A2418" />
    <path d="M14 30 C14 19 20 13 28 13 C36 13 42 19 42 30 L42 33 C40 31 36 30 32 30 L24 30 C20 30 16 31 14 33 Z" fill="#3A2418" />
    {/* face */}
    <ellipse cx="28" cy="31" rx="12" ry="13" fill="#F0C3AE" />
    {/* eyes */}
    <circle cx="23.5" cy="30" r="1.1" fill="#2A2018" />
    <circle cx="32.5" cy="30" r="1.1" fill="#2A2018" />
    {/* blush */}
    <circle cx="20.5" cy="34" r="1.8" fill="#F0A89A" opacity="0.6" />
    <circle cx="35.5" cy="34" r="1.8" fill="#F0A89A" opacity="0.6" />
    {/* smile */}
    <path d="M24.5 37.5 Q28 40 31.5 37.5" stroke="#A24A38" strokeWidth="1.3" fill="none" strokeLinecap="round" />
    {/* blouse */}
    <path d="M15 52 C17 46 22 43 28 43 C34 43 39 46 41 52 Z" fill="#C95F75" />
    <circle cx="28" cy="47" r="1.1" fill="#FFFFFF" />
  </svg>
);

const AvatarTime = () => (
  <svg viewBox="0 0 56 56" width="100%" height="100%" aria-hidden="true">
    <circle cx="28" cy="28" r="28" fill="#E3D7BA" />
    {/* hair */}
    <path d="M13 27 C13 17 19 12 28 12 C37 12 43 17 43 27 L43 29 L13 29 Z" fill="#1F2937" />
    <path d="M13 27 C16 25 19 25 22 26" fill="none" stroke="#1F2937" strokeWidth="0" />
    {/* face */}
    <ellipse cx="28" cy="31" rx="12" ry="13" fill="#D9B48A" />
    {/* eyebrows */}
    <path d="M21 27 L25 27" stroke="#1F2937" strokeWidth="1.2" strokeLinecap="round" />
    <path d="M31 27 L35 27" stroke="#1F2937" strokeWidth="1.2" strokeLinecap="round" />
    {/* eyes */}
    <circle cx="23" cy="30" r="1.1" fill="#1F2937" />
    <circle cx="33" cy="30" r="1.1" fill="#1F2937" />
    {/* mustache */}
    <path d="M23 36 Q28 38 33 36 Q31 37.5 28 37.5 Q25 37.5 23 36 Z" fill="#1F2937" />
    {/* smile */}
    <path d="M25 39 Q28 40.5 31 39" stroke="#5B3A24" strokeWidth="1.1" fill="none" strokeLinecap="round" />
    {/* shirt */}
    <path d="M15 52 C17 46 22 43 28 43 C34 43 39 46 41 52 Z" fill="#3F6F5D" />
    <path d="M28 43 L26 48 L28 50 L30 48 Z" fill="#F4EFE2" />
  </svg>
);

const AvatarTakeoff = () => (
  <svg viewBox="0 0 56 56" width="100%" height="100%" aria-hidden="true">
    <circle cx="28" cy="28" r="28" fill="#D9E3EE" />
    {/* antenna */}
    <line x1="28" y1="14" x2="28" y2="9" stroke="#3F4A5A" strokeWidth="1.4" strokeLinecap="round" />
    <circle cx="28" cy="8" r="1.6" fill="#3FA8E5" />
    {/* head */}
    <rect x="14" y="14" width="28" height="24" rx="7" fill="#F0F3F8" stroke="#3F4A5A" strokeWidth="1.4" />
    {/* screen */}
    <rect x="17" y="19" width="22" height="14" rx="3" fill="#0F1115" />
    {/* eyes */}
    <circle cx="23" cy="26" r="2.2" fill="#3FA8E5" />
    <circle cx="33" cy="26" r="2.2" fill="#3FA8E5" />
    <circle cx="23.4" cy="25.4" r="0.7" fill="#FFFFFF" />
    <circle cx="33.4" cy="25.4" r="0.7" fill="#FFFFFF" />
    {/* mouth */}
    <rect x="24" y="30" width="8" height="1.4" rx="0.7" fill="#3FA8E5" opacity="0.7" />
    {/* ears */}
    <rect x="11" y="22" width="3" height="8" rx="1.4" fill="#C5D1DD" />
    <rect x="42" y="22" width="3" height="8" rx="1.4" fill="#C5D1DD" />
    {/* body */}
    <path d="M16 52 C17 46 21 41 28 41 C35 41 39 46 40 52 Z" fill="#3F6F8F" />
    <circle cx="24" cy="46" r="1" fill="#FFD66B" />
    <circle cx="28" cy="46" r="1" fill="#FF7A6A" />
    <circle cx="32" cy="46" r="1" fill="#7AD18F" />
  </svg>
);

const AvatarScheduler = () => (
  <svg viewBox="0 0 56 56" width="100%" height="100%" aria-hidden="true">
    <circle cx="28" cy="28" r="28" fill="#E8DCC4" />
    {/* hair */}
    <path d="M12 30 C12 17 19 11 28 11 C37 11 44 17 44 30 L44 34 C42 31 38 30 34 30 L34 22 C34 20 31 20 28 21 C24 22 22 24 22 28 L22 30 C18 30 14 31 12 34 Z" fill="#A35A2D" />
    {/* face */}
    <ellipse cx="28" cy="32" rx="12" ry="13" fill="#F2C9A0" />
    {/* eyes */}
    <circle cx="23" cy="30" r="1.1" fill="#3A2418" />
    <circle cx="33" cy="30" r="1.1" fill="#3A2418" />
    {/* freckles */}
    <circle cx="21" cy="33" r="0.5" fill="#A3653A" />
    <circle cx="35" cy="33" r="0.5" fill="#A3653A" />
    <circle cx="24" cy="34" r="0.4" fill="#A3653A" />
    <circle cx="32" cy="34" r="0.4" fill="#A3653A" />
    {/* smile */}
    <path d="M24.5 38 Q28 40.5 31.5 38" stroke="#7A3F1E" strokeWidth="1.3" fill="none" strokeLinecap="round" />
    {/* sweater */}
    <path d="M15 52 C17 46 22 43 28 43 C34 43 39 46 41 52 Z" fill="#8C7AB5" />
    <path d="M22 45 L34 45" stroke="#FFFFFF" strokeWidth="0.8" strokeLinecap="round" opacity="0.5" />
  </svg>
);

const CREW_AVATARS = {
  books:   AvatarBookkeeper,
  field:   AvatarField,
  client:  AvatarClient,
  time:    AvatarTime,
  takeoff: AvatarTakeoff,
  sched:   AvatarScheduler,
};

// Maps each crew member to the screen they own.
const CREW_TARGETS = {
  books:   "bills",
  field:   "field",
  client:  "client",
  time:    "timekeeper",
  takeoff: "takeoff",
  sched:   "schedule",
};

const CrewItem = ({ crew, onGo }) => {
  const Avatar = CREW_AVATARS[crew.id];
  const target = CREW_TARGETS[crew.id];
  const handleClick = () => {
    if (onGo && target) onGo(target);
  };
  return (
    <button
      type="button"
      className="crew-item"
      onClick={handleClick}
      aria-label={"Open " + crew.name}
    >
      <div className="crew-avatar">
        {crew.avatar
          ? <img src={crew.avatar} alt="" loading="eager" />
          : Avatar ? <Avatar /> : null}
      </div>
      <div className="crew-name">{crew.name}</div>
      <div className={"crew-status crew-status--" + crew.status}>
        {crew.status === "review"
          ? <>Review needed</>
          : <><span className="crew-status-dot" /> Working</>}
      </div>
    </button>
  );
};

const CrewStrip = ({ onGo }) => {
  const data = useHomeData();
  return (
    <div className="crew-strip" role="list">
      {data.crew.map((c) => <CrewItem key={c.id} crew={c} onGo={onGo} />)}
    </div>
  );
};

/* =========================================================
   TODAY BRIEFING — dark audio strip with denser waveform
   ========================================================= */

const PlayGlyph = () => (
  <svg width="14" height="14" viewBox="0 0 16 16" aria-hidden="true">
    <path d="M4.5 3 L13 8 L4.5 13 Z" fill="currentColor" />
  </svg>
);
const PauseGlyph = () => (
  <svg width="14" height="14" viewBox="0 0 16 16" aria-hidden="true">
    <rect x="4" y="3" width="3" height="10" fill="currentColor" />
    <rect x="9" y="3" width="3" height="10" fill="currentColor" />
  </svg>
);

const BRIEFING_SCRIPT =
  "Good morning, Jon. Quick office update before you get pulled into the day. " +
  "The Bookkeeper went through the overnight bills. ABC Supply and Northline Concrete are matched to the right jobs and ready for QuickBooks. Sherwin Williams looked like the same invoice from Tuesday, so she held it instead of risking a duplicate. " +
  "Field Intake picked up Marco's Oakwood notes. His voice note is now a daily log, the five photos are filed, and the stair detail is the only thing he still needs answered before the framing crew closes that area. " +
  "Client Liaison has the Ridgeview homeowner update drafted. It reads clean: progress, selected photos, and the next milestones. No vendor noise, no internal budget notes. " +
  "Timekeeper has yesterday's hours staged. Most of the crew matched the rules. Jay Patel has four and a half hours of overtime, so that is waiting for your call. " +
  "Takeoff Reader checked the Oakwood plan change and handed the changed counts to estimating. The budget now includes the new Apex Electric number. " +
  "Scheduler kept the dates lined up with the budget. Six jobs are on track, nothing is overdue, and there are only two things that need you today: the Oakwood budget variance and the Ridgeview cabinet allowance. " +
  "Everything else is moving. Open those two when you have a minute, and the office will keep going from there.";

const BRIEFING_MP3_URL = "/app/uploads/briefing.mp3";

const formatMSS = (sec) => {
  if (!isFinite(sec) || sec <= 0) return "2:37 min";
  const m = Math.floor(sec / 60);
  const s = Math.floor(sec % 60);
  return m + ":" + String(s).padStart(2, "0") + " min";
};

const WAVE_BARS = Array.from({ length: 48 }, (_, i) => {
  // Vary heights between 4 and 28 using overlapping sines for organic feel
  const a = Math.abs(Math.sin(i * 0.55));
  const b = Math.abs(Math.sin(i * 1.7 + 0.4));
  const c = Math.abs(Math.sin(i * 2.9 + 1.1));
  const mix = (a * 0.5 + b * 0.3 + c * 0.2);
  return 4 + Math.round(mix * 24);
});

function pickPreferredVoice(voices) {
  if (!voices || !voices.length) return null;
  const byName = (re) => voices.find((v) => re.test(v.name || ""));
  return (
    byName(/Google US English/i) ||
    byName(/^Samantha/i) ||
    byName(/^Alex/i) ||
    voices.find((v) => /en[-_]US/i.test(v.lang)) ||
    voices.find((v) => /^en/i.test(v.lang)) ||
    voices[0]
  );
}

const TodayBriefing = () => {
  const supported = typeof window !== "undefined" && "speechSynthesis" in window;
  const [speaking, setSpeaking] = React.useState(false);
  const [voice, setVoice] = React.useState(null);
  const [mp3Available, setMp3Available] = React.useState(false);
  const [mp3Duration, setMp3Duration] = React.useState(0);
  const utteranceRef = React.useRef(null);
  const audioRef = React.useRef(null);

  // Probe for studio MP3 voiceover. If present, prefer it over Web Speech.
  React.useEffect(() => {
    let cancelled = false;
    if (typeof fetch !== "function") return undefined;
    fetch(BRIEFING_MP3_URL, { method: "HEAD" })
      .then((res) => {
        if (cancelled || !res || !res.ok) return;
        setMp3Available(true);
        // Preload to read duration for the subtitle.
        const probe = new Audio(BRIEFING_MP3_URL);
        probe.preload = "metadata";
        probe.addEventListener("loadedmetadata", () => {
          if (!cancelled) setMp3Duration(probe.duration || 0);
        });
      })
      .catch(() => { /* MP3 not present — use Web Speech fallback */ });
    return () => { cancelled = true; };
  }, []);

  // Load Web Speech voices for the fallback path.
  React.useEffect(() => {
    if (!supported) return undefined;
    const loadVoices = () => {
      const voices = window.speechSynthesis.getVoices();
      const picked = pickPreferredVoice(voices);
      if (picked) setVoice(picked);
    };
    loadVoices();
    window.speechSynthesis.addEventListener("voiceschanged", loadVoices);
    return () => {
      window.speechSynthesis.removeEventListener("voiceschanged", loadVoices);
      window.speechSynthesis.cancel();
    };
  }, [supported]);

  // Stop any audio on unmount.
  React.useEffect(() => {
    return () => {
      if (audioRef.current) {
        audioRef.current.pause();
        audioRef.current = null;
      }
    };
  }, []);

  const speak = React.useCallback(() => {
    if (mp3Available) {
      if (speaking && audioRef.current) {
        audioRef.current.pause();
        return;
      }
      let audio = audioRef.current;
      if (!audio) {
        audio = new Audio(BRIEFING_MP3_URL);
        audio.addEventListener("play", () => setSpeaking(true));
        audio.addEventListener("pause", () => setSpeaking(false));
        audio.addEventListener("ended", () => setSpeaking(false));
        audio.addEventListener("loadedmetadata", () => setMp3Duration(audio.duration || 0));
        audioRef.current = audio;
      }
      const p = audio.play();
      if (p && typeof p.catch === "function") p.catch(() => setSpeaking(false));
      return;
    }
    if (!supported) return;
    if (speaking) { window.speechSynthesis.cancel(); setSpeaking(false); return; }
    const u = new window.SpeechSynthesisUtterance(BRIEFING_SCRIPT);
    u.rate = 0.96;
    u.pitch = 1;
    const chosen = voice || pickPreferredVoice(window.speechSynthesis.getVoices());
    if (chosen) u.voice = chosen;
    u.onend = () => setSpeaking(false);
    u.onerror = () => setSpeaking(false);
    utteranceRef.current = u;
    window.speechSynthesis.cancel();
    window.speechSynthesis.speak(u);
    setSpeaking(true);
  }, [mp3Available, speaking, supported, voice]);

  // Expose play/pause to a global "P" key listener for the demo presenter.
  React.useEffect(() => {
    window.__playBriefing = speak;
    return () => {
      if (window.__playBriefing === speak) delete window.__playBriefing;
    };
  }, [speak]);

  const canPlay = mp3Available || supported;
  const subtitle = mp3Available
    ? formatMSS(mp3Duration)
    : (supported ? "2:37 min" : "Audio unavailable");

  return (
    <div className="briefing">
      <button
        className="briefing-play"
        type="button"
        onClick={speak}
        disabled={!canPlay}
        aria-label={speaking ? "Pause today's update" : "Play today's update"}
        title={canPlay ? "Play today's update" : "Audio unavailable in this browser"}
      >
        {speaking ? <PauseGlyph /> : <PlayGlyph />}
      </button>
      <div className="briefing-meta">
        <div className="briefing-title">Play Today's Update</div>
        <div className="briefing-sub">{subtitle}</div>
      </div>
      <div className={"briefing-wave" + (speaking ? " is-live" : "")} aria-hidden="true">
        {WAVE_BARS.map((h, i) => (
          <span key={i} style={{ height: h + "px", animationDelay: ((i % 12) * 80) + "ms" }} />
        ))}
      </div>
    </div>
  );
};

/* =========================================================
   STATS ROW + ALL GOOD
   ========================================================= */

const CheckGlyph = ({ size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 16 16" aria-hidden="true">
    <path d="M3.5 8.5 L6.5 11.5 L12.5 5" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
  </svg>
);

const StatsRow = () => {
  const { stats } = useHomeData();
  const items = [
    { top: "Office handled", bottom: stats.handledOvernight + " things overnight" },
    { top: stats.projectsOnTrack + " projects",         bottom: "on track" },
    { top: stats.overdue + " overdue",                  bottom: "items" },
  ];
  return (
    <div className="stats-row">
      {items.map((it, i) => (
        <div key={i} className="stats-item">
          <span className="stats-check"><CheckGlyph size={12} /></span>
          <span className="stats-text"><b>{it.top}</b><span>{it.bottom}</span></span>
        </div>
      ))}
    </div>
  );
};

const AllGoodPanel = () => (
  // CSS keyframe animation handles the 280ms fade + translate-up on mount.
  <div className="allgood">
    <div className="allgood-check"><CheckGlyph size={40} /></div>
    <div className="allgood-text">
      <h2>Everything's on track.</h2>
      <p>We'll only ping you if we need you.</p>
    </div>
  </div>
);

/* =========================================================
   NEEDS ATTENTION — per-kind modals + exit animation
   ========================================================= */

const AttentionCard = ({ item, onResolve }) => {
  const [showWhy, setShowWhy] = React.useState(false);
  const [open, setOpen] = React.useState(false);
  const [isExiting, setIsExiting] = React.useState(false);
  const [selectedOption, setSelectedOption] = React.useState(0);

  const beginExit = () => {
    setOpen(false);
    setIsExiting(true);
    window.setTimeout(() => onResolve(item.id), 320);
  };

  return (
    <div className={"attention-card attention-card--" + item.kind + (isExiting ? " is-exiting" : "")}>
      <div className={"attention-card__tag attention-card__tag--" + item.kind}>{item.tag}</div>
      <div className="attention-card__title">{item.title}</div>
      {item.money && <div className="attention-card__money">{item.money}</div>}
      <div className="attention-card__reasoning-label">Why this needs you</div>
      <div className="attention-card__reasoning">{item.reasoning}</div>
      {showWhy && (
        <ul className="attention-card__why">
          {item.why.map((w, i) => <li key={i}>{w}</li>)}
        </ul>
      )}
      <div className="attention-card__foot">
        <button className="attention-card__see-why" type="button" onClick={() => setShowWhy((v) => !v)}>
          See why {showWhy ? "▴" : "▾"}
        </button>
        <button className="attention-card__cta" type="button" onClick={() => setOpen(true)}>
          {item.cta}
        </button>
      </div>
      {open && (
        <div className="modal-overlay" onClick={() => setOpen(false)}>
          <div className="modal-card" onClick={(e) => e.stopPropagation()}>
            <div className={"modal-card__tag modal-card__tag--" + item.kind}>{item.tag}</div>
            <div className="modal-card__title">{item.title}</div>
            {item.money && <div className="modal-card__money">{item.money}</div>}
            <div className="modal-card__body">
              <p>{item.reasoning}</p>
            </div>

            {item.kind === "budget" && (
              <div className="modal-card__choices modal-card__choices--budget">
                <button type="button" className="modal-choice-pill" onClick={beginExit}>
                  Rebid scope
                </button>
                <button type="button" className="modal-choice-pill" onClick={beginExit}>
                  Adjust allowances
                </button>
              </div>
            )}

            {item.kind === "input" && (
              <div className="modal-card__choices modal-card__choices--input">
                {item.why.map((opt, i) => (
                  <label
                    key={i}
                    className={"modal-radio" + (selectedOption === i ? " is-selected" : "")}
                  >
                    <input
                      type="radio"
                      name={"opt-" + item.id}
                      checked={selectedOption === i}
                      onChange={() => setSelectedOption(i)}
                    />
                    <span className="modal-radio__dot" aria-hidden="true" />
                    <span className="modal-radio__label">{opt}</span>
                  </label>
                ))}
              </div>
            )}

            <div className="modal-card__foot">
              <button type="button" className="modal-card__ghost" onClick={() => setOpen(false)}>Cancel</button>
              {item.kind === "input" && (
                <button type="button" className="modal-card__primary" onClick={beginExit}>
                  Submit
                </button>
              )}
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

const NeedsAttention = () => {
  const data = useHomeData();
  return (
    <section className="attention">
      <header className="attention-head">
        <h2>Needs Your Attention</h2>
        <span className="attention-count">{data.attentionItems.length}</span>
      </header>
      <div className="attention-grid">
        {data.attentionItems.map((item) => (
          <AttentionCard key={item.id} item={item} onResolve={(id) => data.resolveAttention(id)} />
        ))}
      </div>
    </section>
  );
};

/* =========================================================
   LATEST ACTIVITY — real Icon glyphs with tinted square tiles
   ========================================================= */

function formatAgo(min) {
  if (min < 60) return min + "m ago";
  if (min < 1440) return Math.round(min / 60) + "h ago";
  return Math.round(min / 1440) + "d ago";
}

// activity.icon kind -> Icon glyph + pale tint background + darker icon tone.
// "quote" maps to the receipt glyph because ui.jsx has no dedicated quote icon.
const ACTIVITY_ICON_MAP = {
  quote:   { glyph: "receipt", bg: "#FBEAC9", fg: "#9A6A11" }, // pale amber
  invoice: { glyph: "ledger",  bg: "#DDEFE0", fg: "#1F7A3F" }, // pale green
  log:     { glyph: "doc",     bg: "#DCE7F5", fg: "#2B4F87" }, // pale blue
  mail:    { glyph: "mail",    bg: "#E6DFF5", fg: "#5240A0" }, // pale lavender
};

const ActivityTile = ({ kind }) => {
  const cfg = ACTIVITY_ICON_MAP[kind] || ACTIVITY_ICON_MAP.log;
  return (
    <span
      className="activity-icon"
      style={{ background: cfg.bg, color: cfg.fg }}
      aria-hidden="true"
    >
      {typeof Icon === "function" ? <Icon name={cfg.glyph} size={13} color={cfg.fg} /> : null}
    </span>
  );
};

const LatestActivity = ({ onGo }) => {
  const data = useHomeData();
  const [collapsed, setCollapsed] = React.useState(false);
  return (
    <div className="activity-card">
      <header className="activity-head">
        <h3>Latest Activity</h3>
        <button
          type="button"
          className={"activity-toggle" + (collapsed ? " is-collapsed" : "")}
          onClick={() => setCollapsed((c) => !c)}
          aria-label={collapsed ? "Expand activity" : "Collapse activity"}
        >
          ▾
        </button>
      </header>
      {!collapsed && (
        <>
          <ul className="activity-list">
            {data.activity.map((a) => (
              <li key={a.id} className="activity-row">
                <ActivityTile kind={a.icon} />
                <span className="activity-label">{a.label}</span>
                <span className="activity-time">{formatAgo(a.minutesAgo)}</span>
              </li>
            ))}
          </ul>
          <button type="button" className="activity-all" onClick={() => onGo && onGo("project")}>
            View all activity →
          </button>
        </>
      )}
    </div>
  );
};

/* =========================================================
   MY PROJECTS — SVG house thumbnails per project
   ========================================================= */

const slug = (s) => (s || "").toLowerCase().replace(/[^a-z0-9]+/g, "-");

const HouseOakwood = () => (
  // Classic two-story with peaked roof — warm cream / brown
  <svg viewBox="0 0 200 130" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
    <defs>
      <linearGradient id="oakSky" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor="#F5D8AC" />
        <stop offset="100%" stopColor="#E8B377" />
      </linearGradient>
    </defs>
    <rect width="200" height="130" fill="url(#oakSky)" />
    {/* ground */}
    <rect y="105" width="200" height="25" fill="#7A5535" />
    {/* trees */}
    <circle cx="22" cy="98" r="14" fill="#3F6F4A" />
    <rect x="20" y="100" width="4" height="10" fill="#3A2418" />
    <circle cx="180" cy="100" r="12" fill="#3F6F4A" />
    <rect x="178" y="102" width="4" height="9" fill="#3A2418" />
    {/* roof */}
    <polygon points="50,62 100,28 150,62" fill="#5B3A24" />
    <polygon points="50,62 100,34 150,62" fill="#7A4A2E" />
    {/* second story */}
    <rect x="58" y="58" width="84" height="22" fill="#F4EFE2" />
    {/* first story */}
    <rect x="50" y="78" width="100" height="32" fill="#EAD9BD" />
    {/* second-story windows */}
    <rect x="68" y="63" width="14" height="12" fill="#3F4A5A" />
    <line x1="75" y1="63" x2="75" y2="75" stroke="#F4EFE2" strokeWidth="1" />
    <line x1="68" y1="69" x2="82" y2="69" stroke="#F4EFE2" strokeWidth="1" />
    <rect x="118" y="63" width="14" height="12" fill="#3F4A5A" />
    <line x1="125" y1="63" x2="125" y2="75" stroke="#F4EFE2" strokeWidth="1" />
    <line x1="118" y1="69" x2="132" y2="69" stroke="#F4EFE2" strokeWidth="1" />
    {/* first-story windows */}
    <rect x="60" y="84" width="16" height="16" fill="#5B3A24" />
    <rect x="62" y="86" width="12" height="12" fill="#F2D38A" />
    <rect x="124" y="84" width="16" height="16" fill="#5B3A24" />
    <rect x="126" y="86" width="12" height="12" fill="#F2D38A" />
    {/* door */}
    <rect x="93" y="88" width="14" height="22" fill="#5B3A24" />
    <circle cx="103" cy="100" r="0.9" fill="#F2D38A" />
    {/* chimney */}
    <rect x="125" y="36" width="8" height="20" fill="#5B3A24" />
  </svg>
);

const HouseRidgeview = () => (
  // Modern flat-roof with large windows — slate / amber palette
  <svg viewBox="0 0 200 130" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
    <defs>
      <linearGradient id="ridgeSky" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor="#D9C9A6" />
        <stop offset="100%" stopColor="#B5A07A" />
      </linearGradient>
    </defs>
    <rect width="200" height="130" fill="url(#ridgeSky)" />
    <rect y="105" width="200" height="25" fill="#5C4B33" />
    {/* shrubs */}
    <ellipse cx="25" cy="106" rx="16" ry="6" fill="#3F6F4A" />
    <ellipse cx="175" cy="106" rx="18" ry="6" fill="#3F6F4A" />
    {/* upper block */}
    <rect x="40" y="50" width="80" height="30" fill="#2C3340" />
    {/* lower block (wider, offset) */}
    <rect x="30" y="78" width="140" height="30" fill="#F1E6D0" />
    {/* flat-roof overhang */}
    <rect x="28" y="48" width="94" height="4" fill="#1F2530" />
    <rect x="28" y="76" width="144" height="4" fill="#7A6749" />
    {/* huge upper windows */}
    <rect x="46" y="56" width="20" height="18" fill="#F2C36A" />
    <rect x="70" y="56" width="20" height="18" fill="#F2C36A" />
    <rect x="94" y="56" width="20" height="18" fill="#3F4A5A" />
    {/* lower picture window */}
    <rect x="42" y="84" width="50" height="20" fill="#3F4A5A" />
    <line x1="67" y1="84" x2="67" y2="104" stroke="#F1E6D0" strokeWidth="1.2" />
    {/* door */}
    <rect x="100" y="84" width="14" height="22" fill="#2C3340" />
    <rect x="102" y="86" width="10" height="14" fill="#F2C36A" />
    {/* right wing window */}
    <rect x="124" y="86" width="38" height="18" fill="#3F4A5A" />
    <line x1="143" y1="86" x2="143" y2="104" stroke="#F1E6D0" strokeWidth="1.2" />
  </svg>
);

const HouseLakeside = () => (
  // Single-story bungalow with porch — sage / sand palette
  <svg viewBox="0 0 200 130" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
    <defs>
      <linearGradient id="lakeSky" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0%" stopColor="#CEDCD2" />
        <stop offset="100%" stopColor="#A8C2B0" />
      </linearGradient>
    </defs>
    <rect width="200" height="130" fill="url(#lakeSky)" />
    {/* lake */}
    <rect y="98" width="200" height="12" fill="#7AA0C2" />
    <path d="M0 100 Q50 102 100 100 T200 100" stroke="#FFFFFF" strokeWidth="0.6" fill="none" opacity="0.7" />
    {/* ground */}
    <rect y="110" width="200" height="20" fill="#6F8A6C" />
    {/* trees */}
    <circle cx="20" cy="92" r="10" fill="#3F6F4A" />
    <rect x="18" y="93" width="3" height="8" fill="#3A2418" />
    {/* roof */}
    <polygon points="40,72 100,48 160,72" fill="#5B6E55" />
    {/* body */}
    <rect x="44" y="70" width="112" height="38" fill="#EBE4D0" />
    {/* porch overhang */}
    <rect x="80" y="80" width="40" height="3" fill="#5B6E55" />
    <rect x="82" y="80" width="2" height="28" fill="#7A4A2E" />
    <rect x="116" y="80" width="2" height="28" fill="#7A4A2E" />
    {/* windows */}
    <rect x="54" y="82" width="18" height="18" fill="#5B3A24" />
    <rect x="56" y="84" width="14" height="14" fill="#F2D38A" />
    <line x1="63" y1="84" x2="63" y2="98" stroke="#5B3A24" strokeWidth="1" />
    <line x1="56" y1="91" x2="70" y2="91" stroke="#5B3A24" strokeWidth="1" />
    <rect x="128" y="82" width="18" height="18" fill="#5B3A24" />
    <rect x="130" y="84" width="14" height="14" fill="#F2D38A" />
    <line x1="137" y1="84" x2="137" y2="98" stroke="#5B3A24" strokeWidth="1" />
    <line x1="130" y1="91" x2="144" y2="91" stroke="#5B3A24" strokeWidth="1" />
    {/* door */}
    <rect x="93" y="84" width="14" height="24" fill="#7A4A2E" />
    <circle cx="103" cy="96" r="0.9" fill="#F2D38A" />
  </svg>
);

const PROJECT_THUMBS = {
  p1: HouseOakwood,
  p2: HouseRidgeview,
  p3: HouseLakeside,
};

const ProjectTile = ({ project, onOpen }) => {
  const Thumb = PROJECT_THUMBS[project.id];
  return (
    <button className="proj-tile" type="button" onClick={() => onOpen(project)}>
      <div className="proj-thumb">
        {project.thumb
          ? <img src={project.thumb} alt="" loading="lazy" />
          : Thumb ? <Thumb /> : null}
      </div>
      <div className="proj-body">
        <div className="proj-name">{project.name}</div>
        <div className="proj-type">{project.type}</div>
        <div className={"proj-status proj-status--" + slug(project.status)}>
          <span className="proj-status-dot" />
          {project.status}
        </div>
        <div className="proj-budget-row">
          <span>Budget</span><span className="proj-budget-pct">{project.budgetPct}%</span>
        </div>
        <div className="proj-bar">
          <div
            className="proj-bar-fill"
            style={{ width: project.budgetPct + "%" }}
          />
        </div>
      </div>
    </button>
  );
};

const MyProjects = ({ onGo, setProject }) => {
  const data = useHomeData();
  const [toast, setToast] = React.useState("");
  const openProject = (p) => {
    if (setProject) setProject(slug(p.name));
    if (onGo) onGo("project");
  };
  const addProject = () => {
    setToast("Coming soon");
    window.setTimeout(() => setToast(""), 1800);
  };
  return (
    <section className="projects">
      <header className="projects-head"><h3>My Projects</h3></header>
      <div className="projects-grid">
        {data.projects.map((p) => <ProjectTile key={p.id} project={p} onOpen={openProject} />)}
        <button type="button" className="proj-tile proj-tile--add" onClick={addProject}>
          <span className="proj-add-glyph" aria-hidden="true">
            <svg viewBox="0 0 24 24" width="28" height="28">
              <path d="M12 5 L12 19 M5 12 L19 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
            </svg>
          </span>
          <span className="proj-add-label">Add Project</span>
        </button>
      </div>
      {toast && <div className="proj-toast">{toast}</div>}
    </section>
  );
};

/* =========================================================
   MOBILE HEADER + BOTTOM TAB BAR
   ========================================================= */

const BellGlyph = ({ size = 18 }) => (
  <svg width={size} height={size} viewBox="0 0 20 20" aria-hidden="true">
    <path
      d="M5 13 V9.5 C5 6.7 7.2 4.5 10 4.5 C12.8 4.5 15 6.7 15 9.5 V13 L16 14.5 H4 Z"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.4"
      strokeLinejoin="round"
    />
    <path
      d="M8.6 16 C8.7 16.9 9.3 17.3 10 17.3 C10.7 17.3 11.3 16.9 11.4 16"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.4"
      strokeLinecap="round"
    />
    <circle cx="10" cy="3.5" r="0.9" fill="currentColor" />
    <circle cx="15.5" cy="5.5" r="2.4" fill="#FF5A4E" stroke="#FAF7F2" strokeWidth="1.2" />
  </svg>
);

const MobileHeader = () => (
  <div className="home-mobile-header">
    <div className="home-brand">
      {typeof Logo === "function" ? <Logo size={22} /> : null}
      <span className="home-wordmark">CoordOS</span>
    </div>
    <button type="button" className="home-bell" aria-label="Notifications">
      <BellGlyph size={20} />
    </button>
  </div>
);

const TAB_DEFS = [
  { id: "home",     icon: "home",    label: "Home",     target: null      },
  { id: "projects", icon: "receipt", label: "Projects", target: "project" },
  { id: "messages", icon: "mail",    label: "Messages", target: "client"  },
  { id: "more",     icon: "ask",     label: "More",     target: "today"   },
];

const BottomTabBar = ({ onGo }) => {
  // We're rendered inside HomeV1 so "home" is always the active tab.
  const activeId = "home";
  return (
    <nav className="home-tabbar" aria-label="Primary">
      {TAB_DEFS.map((t) => {
        const active = t.id === activeId;
        const click = () => {
          if (!t.target) return; // home no-op when on home
          if (onGo) onGo(t.target);
        };
        return (
          <button
            key={t.id}
            type="button"
            className={"home-tab" + (active ? " is-active" : "")}
            onClick={click}
            aria-current={active ? "page" : undefined}
          >
            <span className="home-tab__icon">
              {typeof Icon === "function" ? <Icon name={t.icon} size={20} color="currentColor" /> : null}
            </span>
            <span className="home-tab__label">{t.label}</span>
            <span className="home-tab__dot" aria-hidden="true" />
          </button>
        );
      })}
    </nav>
  );
};

/* =========================================================
   DEMO HELPERS — keyboard hint toast + global P key listener
   ========================================================= */

const DEMO_HINT_KEY = "coordos-demo-hint-dismissed";

const DemoHintToast = () => {
  const initial = (() => {
    try {
      return typeof window !== "undefined"
        && window.sessionStorage
        && window.sessionStorage.getItem(DEMO_HINT_KEY) === "1";
    } catch (e) { return false; }
  })();
  const [dismissed, setDismissed] = React.useState(initial);

  const dismiss = React.useCallback(() => {
    setDismissed(true);
    try {
      if (window.sessionStorage) window.sessionStorage.setItem(DEMO_HINT_KEY, "1");
    } catch (e) { /* ignore */ }
  }, []);

  React.useEffect(() => {
    if (dismissed) return undefined;
    const id = window.setTimeout(dismiss, 6000);
    return () => window.clearTimeout(id);
  }, [dismissed, dismiss]);

  if (dismissed) return null;
  return (
    <div className="demo-hint" role="status" aria-live="polite">
      <span className="demo-hint__text">
        Press <kbd>R</kbd> to reset demo · Press <kbd>P</kbd> to play briefing
      </span>
      <button
        type="button"
        className="demo-hint__close"
        onClick={dismiss}
        aria-label="Dismiss keyboard hint"
      >
        ×
      </button>
    </div>
  );
};

const useGlobalBriefingKey = () => {
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key !== "p" && e.key !== "P") return;
      if (e.metaKey || e.ctrlKey || e.altKey || e.shiftKey) return;
      const t = e.target;
      const tag = t && t.tagName ? t.tagName.toLowerCase() : "";
      if (tag === "input" || tag === "textarea" || tag === "select") return;
      if (t && t.isContentEditable) return;
      const fn = window.__playBriefing;
      if (typeof fn === "function") {
        e.preventDefault();
        fn();
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);
};

/* =========================================================
   ROOT
   ========================================================= */

const HomeV1 = ({ onGo, setProject }) => {
  const data = useHomeData();
  const hasAttention = data.attentionItems.length > 0;
  useGlobalBriefingKey();
  return (
    <div className="home">
      <header className="home-top">
        <div className="home-brand">
          {typeof Logo === "function" ? <Logo size={28} /> : null}
          <span className="home-wordmark">CoordOS</span>
        </div>
        <CrewStrip onGo={onGo} />
      </header>

      <MobileHeader />
      <div className="home-mobile-crew">
        <CrewStrip onGo={onGo} />
      </div>

      <section className="home-hero">
        <p className="home-greeting">Good morning, {data.user.name}.</p>
        <h1 className="home-headline">Your office<br/>is handling it.</h1>
        <TodayBriefing />
        <StatsRow />
      </section>

      <section className="home-body">
        <div className="home-body-main">
          {hasAttention ? <NeedsAttention /> : <AllGoodPanel />}
        </div>
        <aside className="home-body-side">
          <LatestActivity onGo={onGo} />
        </aside>
      </section>

      <section className="home-projects">
        <MyProjects onGo={onGo} setProject={setProject} />
      </section>

      <BottomTabBar onGo={onGo} />
      <DemoHintToast />
    </div>
  );
};

window.HomeV1 = HomeV1;
