/* global React */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ============ ICONS ============
const Icon = ({ name, size = 16, stroke = 1.5 }) => {
  const paths = {
    search: <><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></>,
    plus: <path d="M12 5v14M5 12h14"/>,
    "plus-sm": <path d="M8 3v10M3 8h10"/>,
    chevron: <path d="m6 9 6 6 6-6"/>,
    "chevron-right": <path d="m9 6 6 6-6 6"/>,
    "more-h": <><circle cx="12" cy="12" r="1"/><circle cx="5" cy="12" r="1"/><circle cx="19" cy="12" r="1"/></>,
    bell: <><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10 21a2 2 0 0 0 4 0"/></>,
    settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></>,
    sidebar: <><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 3v18"/></>,
    inbox: <><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11Z"/></>,
    today: <><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/><circle cx="12" cy="15" r="1.5"/></>,
    archive: <><rect x="2" y="3" width="20" height="5" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></>,
    star: <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>,
    users: <><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></>,
    folder: <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>,
    calendar: <><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></>,
    paperclip: <path d="m21 11-8.5 8.5a5 5 0 1 1-7-7L13.5 4a3.5 3.5 0 0 1 5 5L10 17.5a2 2 0 0 1-3-3L15 7"/>,
    message: <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>,
    check: <polyline points="20 6 9 17 4 12"/>,
    "check-sm": <polyline points="11 4 5 10 2 7"/>,
    clock: <><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></>,
    flag: <><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></>,
    x: <><path d="M18 6 6 18M6 6l18 18"/></>,
    filter: <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>,
    sparkles: <><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.5 5.5l2.8 2.8M15.7 15.7l2.8 2.8M5.5 18.5l2.8-2.8M15.7 8.3l2.8-2.8"/></>,
    layers: <><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></>,
    "layout-grid": <><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></>,
    arrow: <><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></>,
    "menu": <><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></>,
  };
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 24 24"
      fill={name === "star" ? "currentColor" : "none"}
      stroke="currentColor"
      strokeWidth={stroke}
      strokeLinecap="round"
      strokeLinejoin="round"
      style={{ flexShrink: 0 }}
    >
      {paths[name]}
    </svg>
  );
};

// ============ AVATAR ============
const AVATAR_COLORS = [
  ["#8a9dbf", "#6479a3"],
  ["#a99cc7", "#84759f"],
  ["#bf9ba5", "#977380"],
  ["#bfaa92", "#977a5e"],
  ["#94b8a5", "#6e9580"],
  ["#9ab2c1", "#728ea1"],
  ["#a8aab0", "#7d7f86"],
];
const hashName = (n) => {
  let h = 0;
  for (let i = 0; i < n.length; i++) h = (h * 31 + n.charCodeAt(i)) | 0;
  return Math.abs(h);
};
const Avatar = ({ name, size = "sm", title }) => {
  const c = AVATAR_COLORS[hashName(name) % AVATAR_COLORS.length];
  const initials = name
    .split(" ")
    .map((p) => p[0])
    .slice(0, 2)
    .join("")
    .toUpperCase();
  return (
    <span
      className="avatar"
      data-size={size}
      title={title || name}
      style={{ background: `linear-gradient(140deg, ${c[0]}, ${c[1]})` }}
    >
      {initials}
    </span>
  );
};

const AvatarGroup = ({ names, max = 3, size = "sm" }) => {
  const shown = names.slice(0, max);
  const more = names.length - shown.length;
  return (
    <span className="avatar-group">
      {shown.map((n, i) => (
        <Avatar key={n + i} name={n} size={size} />
      ))}
      {more > 0 && (
        <span
          className="avatar"
          data-size={size}
          style={{
            background: "var(--bg-sunken)",
            color: "var(--text-secondary)",
            fontWeight: 600,
          }}
        >
          +{more}
        </span>
      )}
    </span>
  );
};

// ============ TAG ============
const Tag = ({ children, color = "gray" }) => (
  <span className="tag" data-color={color}>
    {children}
  </span>
);

// ============ DATA ============
const TODAY = new Date(2026, 4, 23); // May 23 2026
const dateFmt = (d) => {
  const same = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
  if (same(d, TODAY)) return "Hoje";
  const tomorrow = new Date(TODAY); tomorrow.setDate(TODAY.getDate() + 1);
  if (same(d, tomorrow)) return "Amanhã";
  const months = ["jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez"];
  return `${d.getDate()} ${months[d.getMonth()]}`;
};
const dateState = (d) => {
  const ms = d - TODAY;
  if (ms < -86400000) return "overdue";
  if (ms < 3 * 86400000) return "soon";
  return "normal";
};

const dateAt = (offsetDays) => {
  const d = new Date(TODAY);
  d.setDate(TODAY.getDate() + offsetDays);
  return d;
};

const INITIAL_BOARDS = {
  product: {
    id: "product",
    name: "Lançamento iOS 3.0",
    color: "#7d9bd9",
    description: "Sprint final antes do lançamento público.",
    columns: ["backlog", "this-week", "in-progress", "review", "shipped"],
  },
  marketing: {
    id: "marketing",
    name: "Marketing Q2",
    color: "#c39ad9",
    description: "Campanhas e brand.",
    columns: [],
  },
  personal: {
    id: "personal",
    name: "Pessoal",
    color: "#9ad9b4",
    description: "Tarefas pessoais.",
    columns: [],
  },
};

const INITIAL_COLUMNS = {
  "backlog": { id: "backlog", name: "Backlog", dot: "#b3b6bc", cards: ["c1", "c2", "c3"] },
  "this-week": { id: "this-week", name: "Esta semana", dot: "#7d9bd9", cards: ["c4", "c5", "c6"] },
  "in-progress": { id: "in-progress", name: "Em progresso", dot: "#c39ad9", cards: ["c7", "c8"] },
  "review": { id: "review", name: "Em revisão", dot: "#d9b89a", cards: ["c9"] },
  "shipped": { id: "shipped", name: "Concluído", dot: "#9ad9b4", cards: ["c10", "c11"] },
};

const INITIAL_CARDS = {
  c1: {
    id: "c1",
    title: "Refinar fluxo de onboarding mobile",
    desc: "Reduzir de 5 passos para 3. Considerar autenticação biométrica como atalho na primeira tela.",
    tags: [{ label: "Design", color: "violet" }, { label: "Mobile", color: "blue" }],
    priority: "med",
    due: null,
    assignees: ["Marina Costa", "Diego Tavares"],
    comments: 4,
    attachments: 1,
    checklist: { done: 2, total: 6 },
    completed: false,
  },
  c2: {
    id: "c2",
    title: "Estudar concorrentes diretos",
    desc: "Compilar análise do Linear, Things 3 e Notion. Foco em UX de captura rápida.",
    tags: [{ label: "Research", color: "gray" }],
    priority: "low",
    due: null,
    assignees: ["Helena Ribeiro"],
    comments: 1,
    attachments: 0,
    checklist: null,
    completed: false,
  },
  c3: {
    id: "c3",
    title: "Definir métricas para v3.0",
    tags: [{ label: "Estratégia", color: "amber" }],
    priority: "med",
    due: null,
    assignees: ["Pedro Almeida", "Marina Costa"],
    comments: 0,
    attachments: 2,
    checklist: { done: 0, total: 4 },
    completed: false,
  },
  c4: {
    id: "c4",
    title: "Componente DatePicker acessível",
    desc: "Suporte completo a teclado e VoiceOver. Confirmar com auditoria a11y.",
    tags: [{ label: "Engenharia", color: "blue" }, { label: "A11y", color: "green" }],
    priority: "high",
    due: dateAt(2),
    assignees: ["Diego Tavares", "Sofia Lima"],
    comments: 8,
    attachments: 0,
    checklist: { done: 3, total: 5 },
    completed: false,
  },
  c5: {
    id: "c5",
    title: "Migração para Postgres 16",
    desc: "Janela de manutenção planejada para domingo às 2h.",
    tags: [{ label: "Infra", color: "rose" }],
    priority: "high",
    due: dateAt(1),
    assignees: ["Bruno Santos"],
    comments: 12,
    attachments: 3,
    checklist: { done: 8, total: 12 },
    completed: false,
  },
  c6: {
    id: "c6",
    title: "Texto da página de pricing",
    tags: [{ label: "Conteúdo", color: "amber" }],
    priority: "med",
    due: dateAt(4),
    assignees: ["Helena Ribeiro"],
    comments: 2,
    attachments: 0,
    checklist: null,
    completed: false,
  },
  c7: {
    id: "c7",
    title: "Drag and drop com inércia em iOS",
    desc: "Implementar trajetória pós-soltura com easing natural e haptic feedback.",
    tags: [{ label: "Engenharia", color: "blue" }, { label: "Mobile", color: "blue" }],
    priority: "high",
    due: dateAt(0),
    assignees: ["Diego Tavares", "Marina Costa", "Sofia Lima"],
    comments: 23,
    attachments: 5,
    checklist: { done: 7, total: 9 },
    completed: false,
  },
  c8: {
    id: "c8",
    title: "Animações de transição entre views",
    tags: [{ label: "Design", color: "violet" }, { label: "Motion", color: "rose" }],
    priority: "med",
    due: dateAt(3),
    assignees: ["Marina Costa"],
    comments: 6,
    attachments: 2,
    checklist: { done: 2, total: 4 },
    completed: false,
  },
  c9: {
    id: "c9",
    title: "Revisão final do design system 2.0",
    desc: "Pareamento de cores, espaçamentos e densidade compacta vs confortável.",
    tags: [{ label: "Design", color: "violet" }],
    priority: "high",
    due: dateAt(1),
    assignees: ["Marina Costa", "Pedro Almeida"],
    comments: 14,
    attachments: 1,
    checklist: { done: 11, total: 12 },
    completed: false,
  },
  c10: {
    id: "c10",
    title: "Configurar pipeline de release",
    tags: [{ label: "Infra", color: "rose" }],
    priority: "med",
    due: dateAt(-3),
    assignees: ["Bruno Santos"],
    comments: 3,
    attachments: 0,
    checklist: { done: 4, total: 4 },
    completed: true,
  },
  c11: {
    id: "c11",
    title: "Roteiro do vídeo de lançamento",
    tags: [{ label: "Conteúdo", color: "amber" }],
    priority: "low",
    due: dateAt(-5),
    assignees: ["Helena Ribeiro", "Pedro Almeida"],
    comments: 9,
    attachments: 4,
    checklist: null,
    completed: true,
  },
};

Object.assign(window, {
  Icon,
  Avatar,
  AvatarGroup,
  Tag,
  TODAY,
  dateFmt,
  dateState,
  dateAt,
  INITIAL_BOARDS,
  INITIAL_COLUMNS,
  INITIAL_CARDS,
});
