// Reusable UI primitives: Sidebar, Topbar, Charts, etc.

const Avatar = ({ id, size = 22 }) => {
  const u = window.USER_BY_ID(id) || { name: "?" };
  return (
    <span className={`av av-${u.name}`} style={{ width: size, height: size, fontSize: size * 0.42 }}>
      {u.name[0]}
    </span>
  );
};

const AvatarGroup = ({ ids, size = 22 }) => (
  <span className="av-group">{ids.map(id => <Avatar key={id} id={id} size={size} />)}</span>
);

const Badge = ({ children, tone = "" }) => (
  <span className={`badge ${tone}`}>{children}</span>
);

// ============================================================
// SIDEBAR
// ============================================================
const NAV = [
  { id: "dashboard",   label: "Dashboard",     icon: "dashboard" },
  { id: "propositions",label: "Propositions",  icon: "bullhorn",  countKey: "propositions" },
  { id: "projects",    label: "Projets",       icon: "car",       countKey: "projects" },
  { id: "sales",       label: "Mises en vente",icon: "tag",       countKey: "sales" },
  { id: "history",     label: "Historique",    icon: "archive" },
];

const NAV_USER = [
  { id: "profile",     label: "Mon profil",    icon: "user" },
];

const Sidebar = ({ route, setRoute }) => {
  const counts = window.NAV_COUNTS || {};
  const me = window.CURRENT_USER || window.USER_BY_ID(window.ME) || { name: "Utilisateur", role: "associé" };
  // Detail pages should highlight their parent section in the sidebar.
  const activeId = (() => {
    if (route.page === "propositionDetail") return "propositions";
    if (route.page === "projectDetail")     return "projects";
    return route.page;
  })();
  return (
    <aside className="sidebar">
      <div className="s-brand">
        <div className="s-logo">G</div>
        <div>
          <div className="s-brand-name">Garage&nbsp;Co.</div>
          <div className="s-brand-sub">3 associés</div>
        </div>
      </div>
      <nav className="s-nav">
        <div className="s-label">Atelier</div>
        {NAV.map(n => (
          <button key={n.id}
            className={`s-item ${activeId === n.id ? "active" : ""}`}
            onClick={() => setRoute({ page: n.id })}>
            <Icon name={n.icon} />
            <span>{n.label}</span>
            {n.countKey && counts[n.countKey] != null && <span className="s-count">{counts[n.countKey]}</span>}
          </button>
        ))}
        <div className="s-label">Personnel</div>
        {NAV_USER.map(n => (
          <button key={n.id}
            className={`s-item ${activeId === n.id ? "active" : ""}`}
            onClick={() => setRoute({ page: n.id })}>
            <Icon name={n.icon} />
            <span>{n.label}</span>
          </button>
        ))}
      </nav>
      <div className="s-foot" style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <button
          type="button"
          onClick={() => setRoute({ page: "profile" })}
          title="Ouvrir mon profil"
          style={{
            flex: 1, minWidth: 0,
            display: "flex", alignItems: "center", gap: 10,
            background: "none", border: 0, padding: 0,
            color: "inherit", textAlign: "left", cursor: "pointer",
          }}
        >
          <Avatar id={me.id || window.ME} size={28} />
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="s-foot-name">{me.name}</div>
            <div className="s-foot-sub">{me.email || me.role}</div>
          </div>
        </button>
        <button
          type="button"
          onClick={() => window.API?.logout()}
          title="Se déconnecter"
          className="btn-icon"
          style={{
            width: 28, height: 28, padding: 0,
            display: "grid", placeItems: "center",
            background: "transparent", border: 0, borderRadius: 6,
            color: "var(--fg-3)", cursor: "pointer",
          }}
          onMouseEnter={(e) => { e.currentTarget.style.background = "var(--surface-2)"; e.currentTarget.style.color = "var(--fg)"; }}
          onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; e.currentTarget.style.color = "var(--fg-3)"; }}
        >
          <Icon name="logout" size={15} />
        </button>
      </div>
    </aside>
  );
};

// ============================================================
// SEARCH
// ============================================================
const SearchBar = ({ setRoute }) => {
  const [q, setQ] = React.useState("");
  const [open, setOpen] = React.useState(false);
  const inputRef = React.useRef(null);
  const wrapRef  = React.useRef(null);

  // Raccourci clavier ⌘+K / Ctrl+K
  React.useEffect(() => {
    function onKey(ev) {
      if ((ev.metaKey || ev.ctrlKey) && ev.key.toLowerCase() === "k") {
        ev.preventDefault();
        inputRef.current?.focus();
        setOpen(true);
      }
      if (ev.key === "Escape") {
        setOpen(false);
        inputRef.current?.blur();
      }
    }
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  // Ferme le dropdown quand on clique ailleurs
  React.useEffect(() => {
    function onClick(ev) {
      if (wrapRef.current && !wrapRef.current.contains(ev.target)) setOpen(false);
    }
    if (open) {
      document.addEventListener("mousedown", onClick);
      return () => document.removeEventListener("mousedown", onClick);
    }
  }, [open]);

  const norm = (s) => (s || "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
  const query = norm(q).trim();

  const results = React.useMemo(() => {
    if (query.length < 2) return [];
    const out = [];

    const props = window.PROPOSITIONS || [];
    const projs = window.PROJECTS || [];
    const hist  = window.HISTORY || [];

    props.forEach(p => {
      const hay = norm([p.title, p.brand, p.model, p.year, p.id].join(" "));
      if (hay.includes(query)) {
        out.push({
          type: "proposition",
          label: `${p.title} (${p.year})`,
          sub: `Proposition · ${window.fmt.km(p.km)} · ${window.fmt.eur(p.askPrice)}`,
          id: p.id,
          icon: "bullhorn",
        });
      }
    });

    projs.forEach(p => {
      const hay = norm([p.title, p.year, p.id].join(" "));
      if (hay.includes(query)) {
        out.push({
          type: "project",
          label: `${p.title} (${p.year})`,
          sub: `Projet · ${window.STATES[p.state]?.label || p.state} · réf ${p.id}`,
          id: p.id,
          icon: "car",
        });
      }
    });

    hist.forEach(p => {
      const hay = norm([p.title, p.year, p.id].join(" "));
      if (hay.includes(query)) {
        out.push({
          type: "sale",
          label: `${p.title} (${p.year})`,
          sub: `Vendu · ${window.fmt.eur(p.soldPrice)} · ${p.soldAt}`,
          id: p.id,
          icon: "tag",
        });
      }
    });

    return out.slice(0, 10);
  }, [query]);

  function go(r) {
    setOpen(false);
    setQ("");
    if (r.type === "proposition") window.AppRouter.navigate({ page: "propositionDetail", id: r.id });
    else if (r.type === "project") window.AppRouter.navigate({ page: "projectDetail", id: r.id });
    else if (r.type === "sale") window.AppRouter.navigate({ page: "saleDetail", id: r.id });
  }

  return (
    <div ref={wrapRef} style={{ position: "relative" }}>
      <div className="tb-search" style={{ cursor: "text" }}>
        <Icon name="search" size={14} />
        <input
          ref={inputRef}
          type="text"
          placeholder="Rechercher…"
          value={q}
          onChange={(ev) => { setQ(ev.target.value); setOpen(true); }}
          onFocus={() => setOpen(true)}
          style={{
            background: "transparent",
            border: "none",
            color: "var(--fg)",
            fontSize: 12.5,
            fontFamily: "inherit",
            outline: "none",
            flex: 1,
            minWidth: 0,
            padding: 0,
            height: 18,
            lineHeight: 1,
          }}
        />
        <kbd>⌘ K</kbd>
      </div>

      {open && (
        <div style={{
          position: "absolute", top: "calc(100% + 8px)", right: 0,
          width: 380, maxHeight: 420,
          background: "var(--surface)", border: "1px solid var(--border)",
          borderRadius: 12, boxShadow: "0 20px 60px rgba(0,0,0,0.35)",
          zIndex: 1000, overflow: "hidden",
          display: "flex", flexDirection: "column",
        }}>
          <div style={{ overflowY: "auto", flex: 1, padding: "4px 0" }}>
            {query.length < 2 ? (
              <div className="muted" style={{ padding: 16, textAlign: "center", fontSize: 12 }}>
                Tape au moins 2 caractères pour chercher.
              </div>
            ) : results.length === 0 ? (
              <div className="muted" style={{ padding: 16, textAlign: "center", fontSize: 12 }}>
                Aucun résultat pour « {q} »
              </div>
            ) : (
              results.map((r, i) => (
                <button
                  key={i}
                  type="button"
                  onClick={() => go(r)}
                  style={{
                    display: "flex", alignItems: "center", gap: 10,
                    width: "100%", padding: "8px 14px",
                    background: "transparent", border: "none",
                    color: "var(--fg)", textAlign: "left", cursor: "pointer",
                  }}
                  onMouseEnter={(e) => { e.currentTarget.style.background = "var(--surface-hi)"; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; }}
                >
                  <div style={{
                    width: 32, height: 32, borderRadius: 8,
                    background: "var(--surface-2)",
                    display: "grid", placeItems: "center",
                    color: "var(--fg-2)", flexShrink: 0,
                  }}>
                    <Icon name={r.icon} size={15} />
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 500, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{r.label}</div>
                    <div className="muted" style={{ fontSize: 11.5, marginTop: 1 }}>{r.sub}</div>
                  </div>
                  <span style={{ color: "var(--fg-4)", flexShrink: 0 }}>
                    <Icon name="chev_r" size={12} stroke={1.5} />
                  </span>
                </button>
              ))
            )}
          </div>
        </div>
      )}
    </div>
  );
};

// ============================================================
// TOPBAR
// ============================================================
const Topbar = ({ crumbs, actions }) => (
  <header className="topbar">
    <div className="crumbs">
      {crumbs.map((c, i) => (
        <React.Fragment key={i}>
          {i > 0 && <span className="sep"><Icon name="chev_r" size={12} stroke={1.6} /></span>}
          <span className={i === crumbs.length - 1 ? "cur" : ""}>{c}</span>
        </React.Fragment>
      ))}
    </div>
    <div className="tb-spacer" />
    <SearchBar />
    <button type="button" className="tb-btn btn-icon" title="Notifications" onClick={() => window.AppUI?.notice("Aucune notification pour le moment.")}>
      <Icon name="bell" size={15} />
    </button>
    {actions}
  </header>
);

// ============================================================
// CHARTS — hand-drawn SVG
// ============================================================
const LineAreaChart = ({ data, height = 200, valueKey = "revenue", valueKey2 = "expenses" }) => {
  const w = 720;
  const h = height;
  const padL = 36, padR = 12, padT = 12, padB = 24;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;
  const max = Math.max(...data.flatMap(d => [d[valueKey], d[valueKey2]])) * 1.15 || 1;
  const x = (i) => padL + (i / (data.length - 1)) * innerW;
  const y = (v) => padT + innerH - (v / max) * innerH;

  const path1 = data.map((d, i) => `${i === 0 ? "M" : "L"} ${x(i)} ${y(d[valueKey])}`).join(" ");
  const area1 = `${path1} L ${x(data.length - 1)} ${padT + innerH} L ${x(0)} ${padT + innerH} Z`;
  const path2 = data.map((d, i) => `${i === 0 ? "M" : "L"} ${x(i)} ${y(d[valueKey2])}`).join(" ");

  const ticks = 4;
  const gridY = Array.from({ length: ticks + 1 }, (_, i) => (max / ticks) * i);

  return (
    <svg className="chart-svg" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      {gridY.map((v, i) => (
        <g key={i}>
          <line className="chart-grid" x1={padL} x2={w - padR} y1={y(v)} y2={y(v)} />
          <text className="chart-axis" x={padL - 6} y={y(v) + 3} textAnchor="end">{window.fmt.eurShort(v)}</text>
        </g>
      ))}
      <path d={area1} className="chart-area" />
      <path d={path1} className="chart-line" />
      <path d={path2} className="chart-line" style={{ stroke: "var(--fg-4)", strokeDasharray: "3 3" }} />
      {data.map((d, i) => (
        <g key={i}>
          <circle className="chart-dot" cx={x(i)} cy={y(d[valueKey])} r="3" />
          <text className="chart-axis" x={x(i)} y={h - 6} textAnchor="middle">{d.m}</text>
        </g>
      ))}
    </svg>
  );
};

const BarChart = ({ data, height = 180, valueKey = "value", labelKey = "label" }) => {
  const w = 480;
  const h = height;
  const padL = 36, padR = 8, padT = 8, padB = 26;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;
  const max = Math.max(...data.map(d => d[valueKey])) * 1.1 || 1;
  const bw = (innerW / data.length) * 0.6;
  const step = innerW / data.length;

  const ticks = 3;
  const gridY = Array.from({ length: ticks + 1 }, (_, i) => (max / ticks) * i);
  return (
    <svg className="chart-svg" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      {gridY.map((v, i) => {
        const y = padT + innerH - (v / max) * innerH;
        return (
          <g key={i}>
            <line className="chart-grid" x1={padL} x2={w - padR} y1={y} y2={y} />
            <text className="chart-axis" x={padL - 6} y={y + 3} textAnchor="end">{window.fmt.eurShort(v)}</text>
          </g>
        );
      })}
      {data.map((d, i) => {
        const x = padL + step * i + (step - bw) / 2;
        const bh = (d[valueKey] / max) * innerH;
        const y = padT + innerH - bh;
        return (
          <g key={i}>
            <rect className={d.muted ? "chart-bar-2" : "chart-bar"} x={x} y={y} width={bw} height={bh} rx="3" />
            <text className="chart-axis" x={x + bw / 2} y={h - 8} textAnchor="middle">{d[labelKey]}</text>
          </g>
        );
      })}
    </svg>
  );
};

const Donut = ({ data, size = 140 }) => {
  const total = data.reduce((a, d) => a + d.value, 0);
  const r = size / 2 - 8;
  const cx = size / 2, cy = size / 2;
  let acc = 0;
  const arcs = data.map((d, i) => {
    const start = (acc / total) * 2 * Math.PI - Math.PI / 2;
    acc += d.value;
    const end = (acc / total) * 2 * Math.PI - Math.PI / 2;
    const large = end - start > Math.PI ? 1 : 0;
    const x1 = cx + r * Math.cos(start), y1 = cy + r * Math.sin(start);
    const x2 = cx + r * Math.cos(end),   y2 = cy + r * Math.sin(end);
    return (
      <path key={i} d={`M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2} Z`}
            fill={d.color} stroke="var(--surface)" strokeWidth="2" />
    );
  });
  return (
    <div className="donut-wrap">
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        {arcs}
        <circle cx={cx} cy={cy} r={r * 0.58} fill="var(--surface)" />
        <text x={cx} y={cy - 4} textAnchor="middle" fill="var(--fg-3)" fontSize="10" fontFamily="var(--font-mono)">TOTAL</text>
        <text x={cx} y={cy + 12} textAnchor="middle" fill="var(--fg)" fontSize="14" fontFamily="var(--font-mono)" fontWeight="500">{window.fmt.eurShort(total)}</text>
      </svg>
      <div className="donut-legend">
        {data.map((d, i) => (
          <div key={i} className="donut-lg-item">
            <span className="donut-sw" style={{ background: d.color }}></span>
            <span style={{ flex: 1 }}>{d.label}</span>
            <span className="mono muted">{window.fmt.eur(d.value)}</span>
          </div>
        ))}
      </div>
    </div>
  );
};

const Spark = ({ data, w = 100, h = 28, positive = true }) => {
  const max = Math.max(...data);
  const min = Math.min(...data);
  const range = max - min || 1;
  const x = (i) => (i / (data.length - 1)) * w;
  const y = (v) => h - 2 - ((v - min) / range) * (h - 4);
  const path = data.map((v, i) => `${i === 0 ? "M" : "L"} ${x(i)} ${y(v)}`).join(" ");
  const col = positive ? "var(--pos)" : "var(--neg)";
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
      <path d={path} stroke={col} fill="none" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
};

const VehPlaceholder = ({ label = "photo véhicule" }) => (
  <div className="veh-img">
    <Icon name="image" size={28} />
    <div className="veh-img-tag">{label}</div>
  </div>
);

// Shared little building blocks used by several pages.
const StatCard = ({ label, value, delta, positive, sub, sparkData, icon }) => (
  <div className="card stat-card">
    <div className="stat-lbl">
      {icon && <Icon name={icon} size={13} />}
      {label}
    </div>
    <div className="stat-val">{value}</div>
    <div className="hstack" style={{ marginTop: 6, justifyContent: "space-between" }}>
      {delta && (
        <div className={`stat-delta ${positive ? "pos" : "neg"}`}>
          <Icon name={positive ? "arrow_ur" : "arrow_dr"} size={11} stroke={2} />
          {delta}
        </div>
      )}
      {sub && !delta && <div className="muted" style={{ fontSize: 11.5 }}>{sub}</div>}
      {sparkData && <Spark data={sparkData} positive={positive} />}
    </div>
    {sub && delta && <div className="muted" style={{ fontSize: 11.5, marginTop: 4 }}>{sub}</div>}
  </div>
);

const Comment = ({ who, time, text }) => (
  <div className="comment">
    <Avatar id={who} size={28} />
    <div className="comment-body">
      <div className="comment-head">
        <span className="comment-name">{window.USER_BY_ID(who).name}</span>
        <span className="comment-time">{time}</span>
      </div>
      <div className="comment-text">{text}</div>
    </div>
  </div>
);

const Kpi = ({ lbl, v, sub, positive }) => (
  <div>
    <div className="tiny">{lbl}</div>
    <div className="num-lg" style={{ marginTop: 4, color: positive ? "var(--pos)" : "var(--fg)" }}>{v}</div>
    {sub && <div className="muted mono" style={{ fontSize: 11, marginTop: 3 }}>{sub}</div>}
  </div>
);

const LegRow = ({ sw, lbl, v }) => (
  <div className="hstack" style={{ fontSize: 12 }}>
    <span style={{ width: 10, height: 10, background: sw, borderRadius: 3 }}></span>
    <span style={{ flex: 1 }}>{lbl}</span>
    <span className="mono">{v}</span>
  </div>
);

const Pref = ({ label, v }) => (
  <div className="hstack" style={{ padding: "6px 0", borderBottom: "1px solid var(--border-soft)" }}>
    <span style={{ flex: 1 }}>{label}</span>
    <span className="muted mono" style={{ fontSize: 12 }}>{v}</span>
  </div>
);

const StatMini = ({ lbl, v, icon }) => (
  <div>
    <div className="hstack muted" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: ".06em" }}>
      <Icon name={icon} size={11} />
      <span>{lbl}</span>
    </div>
    <div className="num-lg" style={{ fontSize: 18, marginTop: 4 }}>{v}</div>
  </div>
);

Object.assign(window, {
  Avatar, AvatarGroup, Badge,
  Sidebar, Topbar, SearchBar,
  LineAreaChart, BarChart, Donut, Spark,
  VehPlaceholder,
  StatCard, Comment, Kpi, LegRow, Pref, StatMini,
});
