// Seed data — Gill is leaving the Atlas team. Eight contributors so far.
// Each note has type (text/photo/voice/doodle/gif/sticker), color, position,
// rotation, scale, author, body, and a "pinned" decoration style.

const PALETTE = {
  warm: {
    bg: "#FAF7F2",
    notes: ["#FFD9A8", "#C5DCC2", "#F4B6C2", "#FFE9A8", "#DCD0F0", "#BFDDEE", "#F5ECDA"],
    accent: "#E87E5A",
  },
  jewel: {
    bg: "#F1ECE2",
    notes: ["#E8B4A0", "#A3C7A1", "#C99CBB", "#D9C36A", "#9AA5D6", "#85B3CC", "#D6BFA1"],
    accent: "#C0563D",
  },
  paper: {
    bg: "#F4F1EB",
    notes: ["#F6F2EA", "#EFE9DC", "#EAE2D2", "#F2EDE2", "#EBE4D4", "#E6DECC", "#F0EADB"],
    accent: "#1F1B17",
  },
};

const STICKER_PACKS = {
  hearts:   ["♥","🤍","💛","💚","💜","✨","✿","☘"],
  paper:    ["✦","✿","❀","✺","✧","◍","☼","◐"],
  letters:  ["★","◆","■","▲","●","◇","☆","✚"],
};

const AUTHORS = [
  { id: "u1", name: "Sana K.",       hue: "#E87E5A" },
  { id: "u2", name: "Theo R.",       hue: "#5C8B6B" },
  { id: "u3", name: "Jules M.",      hue: "#B86A8A" },
  { id: "u4", name: "Priya N.",      hue: "#C18A3B" },
  { id: "u5", name: "Marco S.",      hue: "#6C7AB1" },
  { id: "u6", name: "Anaïs B.",      hue: "#3F8FA8" },
  { id: "u7", name: "Devon L.",      hue: "#9C6BB1" },
  { id: "u8", name: "Kenji T.",      hue: "#A86A5A" },
  { id: "me", name: "You",           hue: "#1F1B17" },
];

// Notes laid out on a 2200x1300 logical canvas. Position is top-left of the
// note element (before rotation). Sizes vary by content.
const SEED_NOTES = [
  {
    id: "n1", type: "text", color: "#FFD9A8", x: 130, y: 110, w: 260, h: 240, rot: -4,
    authorId: "u1",
    body: "Gill — three years of catching every typo I missed and somehow making the deadlines feel calmer. Atlas is losing its quiet superpower. Wishing you the brightest next chapter. ♥",
    sticker: "♥",
  },
  {
    id: "n2", type: "photo", color: "#FFFFFF", x: 470, y: 90, w: 280, h: 320, rot: 3,
    authorId: "u2",
    caption: "Brooklyn offsite, 2023 — you wouldn't stop laughing at the boba menu",
    photoHue: 218,
    photoLabel: "team photo",
  },
  {
    id: "n3", type: "text", color: "#C5DCC2", x: 850, y: 130, w: 230, h: 210, rot: -2,
    authorId: "u3",
    body: "Lunch buddy, gossip partner, ruthless eyebrow-raiser at bad ideas. I'll miss our walks. Don't be a stranger.",
    sticker: "🤍",
  },
  {
    id: "n4", type: "voice", color: "#DCD0F0", x: 1160, y: 110, w: 280, h: 170, rot: 4,
    authorId: "u4",
    duration: 22,
    transcript: "Hey Gill — couldn't write this one down, you'd see right through me…",
  },
  {
    id: "n5", type: "doodle", color: "#FFE9A8", x: 1520, y: 90, w: 250, h: 230, rot: -6,
    authorId: "u5",
    body: "go bake bread!",
  },
  {
    id: "n6", type: "text", color: "#F4B6C2", x: 1820, y: 130, w: 230, h: 200, rot: 2,
    authorId: "u6",
    body: "From your loudest defender in the back row. Go and be excellent, my friend.",
    sticker: "✨",
  },
  {
    id: "n7", type: "text", color: "#BFDDEE", x: 200, y: 410, w: 250, h: 210, rot: 3,
    authorId: "u7",
    body: "Onboarded by you. Trained by you. Ruined for any other manager. Thanks for everything.",
  },
  {
    id: "n8", type: "gif", color: "#FFFFFF", x: 510, y: 460, w: 240, h: 240, rot: -3,
    authorId: "u8",
    caption: "still our shared screenshot.",
    photoHue: 36,
    photoLabel: "looped gif",
  },
  {
    id: "n9", type: "text", color: "#F5ECDA", x: 830, y: 430, w: 260, h: 230, rot: -2,
    authorId: "u1",
    body: "You made the team feel like a team. I'll remember the way you said “let's do it properly” and meant it.",
  },
  {
    id: "n10", type: "sticker-cluster", color: "transparent", x: 1140, y: 480, w: 220, h: 180, rot: 0,
    authorId: "u2",
    stickers: ["♥","✨","✿","☘","✦"],
  },
  {
    id: "n11", type: "text", color: "#DCD0F0", x: 1390, y: 440, w: 250, h: 220, rot: 5,
    authorId: "u3",
    body: "If you ever want to come back, we'll keep your chair warm. (Not really. We threw it out. Kidding.)",
    sticker: "★",
  },
  {
    id: "n12", type: "photo", color: "#FFFFFF", x: 1700, y: 470, w: 270, h: 290, rot: -4,
    authorId: "u5",
    caption: "the day you presented the rebrand and nailed it",
    photoHue: 12,
    photoLabel: "presentation photo",
  },
  {
    id: "n13", type: "text", color: "#C5DCC2", x: 280, y: 770, w: 240, h: 200, rot: -5,
    authorId: "u4",
    body: "Thanks for the Friday playlists. The office speaker will be on mute forever.",
  },
  {
    id: "n14", type: "text", color: "#FFD9A8", x: 590, y: 800, w: 280, h: 230, rot: 4,
    authorId: "u6",
    body: "Gill, you are the reason I stayed past month two. Please go on and be impossible. I'm cheering.",
    sticker: "☘",
  },
  {
    id: "n15", type: "doodle", color: "#F4B6C2", x: 930, y: 760, w: 240, h: 210, rot: -1,
    authorId: "u7",
    body: "✿  see you soon  ✿",
  },
];

// Pending / hidden examples for admin queue
const PENDING_NOTES = [
  {
    id: "p1", type: "text", color: "#FFD9A8", w: 240, h: 180, rot: 0,
    authorId: "u8",
    body: "Gill you are literally my favourite person at work, I'm devastated, but also extremely happy for you. ♡",
  },
  {
    id: "p2", type: "photo", color: "#FFFFFF", w: 240, h: 240, rot: 0,
    authorId: "u3",
    caption: "the holiday party",
    photoHue: 320,
    photoLabel: "photo",
  },
];

// Stable color from a user's name — keeps the avatar circle consistent
// across renders and devices without needing a server-side `hue` column.
const AVATAR_HUES = ["#E87E5A", "#5C8B6B", "#B86A8A", "#C18A3B", "#6C7AB1", "#3F8FA8", "#9C6BB1", "#A86A5A"];
function hueFromName(name) {
  const s = String(name || "?");
  let h = 0;
  for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0;
  return AVATAR_HUES[Math.abs(h) % AVATAR_HUES.length];
}

// Strip content fields, keep geometry + author. Used to mirror the server's
// redaction client-side when an admin previews a non-admin POV — the server
// gladly hands an admin the full data, but we shouldn't render it when
// they're pretending to be a contributor or recipient.
function redactNote(note) {
  const {
    body, caption,
    photoSrc, photoLabel, photoHue,
    audioSrc, transcript, duration,
    sticker, stickers,
    paths, doodleVW, doodleVH,
    ...keep
  } = note;
  return { ...keep, redacted: true };
}

// Apply the redaction rules used by the contributor view. Admin and
// recipient previews see everything (recipient is an admin-only preview of
// the final unveiled board).
//   - admin POV    → see everything.
//   - recipient POV → see everything (admin-gated preview).
//   - contributor  → public + own visible; everything else redacted.
function applyClientRedaction(notes, role, myUserId) {
  if (role === "admin" || role === "recipient") return notes;
  return notes.map((n) => {
    if (n.redacted) return n;                                  // server already did this
    if (n.visibility === "public") return n;                   // visible to all
    if (myUserId && n.authorId === myUserId) return n;         // own
    return redactNote(n);
  });
}

// Resolve the author shape ({name, hue}) for a note, supporting both:
//   - real users: note.authorName + note.authorHue (denormalized at create)
//   - demo seed:  note.authorId mapped through the legacy AUTHORS table
function authorForNote(note) {
  if (!note) return null;
  if (note.authorName) {
    return { name: note.authorName, hue: note.authorHue || hueFromName(note.authorName) };
  }
  if (note.authorId) {
    return AUTHORS.find((a) => a.id === note.authorId) || null;
  }
  return null;
}

// Reactive viewport hook — returns true when the screen is phone-width.
// Threshold matches the @media (max-width: 720px) block in index.html so
// CSS and JSX agree on what "mobile" means.
function useIsMobile(maxWidth = 720) {
  const query = `(max-width: ${maxWidth}px)`;
  const get = () => typeof window !== "undefined" && window.matchMedia(query).matches;
  const [is, setIs] = React.useState(get);
  React.useEffect(() => {
    const mql = window.matchMedia(query);
    const onChange = () => setIs(mql.matches);
    // Safari < 14 uses the deprecated addListener API.
    if (mql.addEventListener) mql.addEventListener("change", onChange);
    else mql.addListener(onChange);
    return () => {
      if (mql.removeEventListener) mql.removeEventListener("change", onChange);
      else mql.removeListener(onChange);
    };
  }, [query]);
  return is;
}

Object.assign(window, {
  PALETTE, STICKER_PACKS, AUTHORS, SEED_NOTES, PENDING_NOTES,
  hueFromName, authorForNote, redactNote, applyClientRedaction,
  useIsMobile,
});
