/* ============================================================
   EDUCARE — Layout: Sidebar, TopBar, RightRail, AppShell
   ============================================================ */
(function () {
  const { useState, useEffect } = React;
  const Icon = window.Icon, Logo = window.Logo;

  // Classificação de erro ao salvar (usada por todos os testes). Loga sempre o
  // erro completo no console e devolve uma mensagem específica por causa.
  // Obs.: hoje a persistência é localStorage — a falha típica é cota estourada
  // (áudios base64). Quando houver backend, este mesmo ponto tratará 401/413/5xx.
  window.classifyStorageError = function (e) {
    try { console.error("[Educare] Falha ao salvar:", { name: e && e.name, code: e && e.code, message: e && e.message, status: e && e.status, error: e }); } catch (_) { /* */ }
    if (typeof navigator !== "undefined" && navigator.onLine === false) {
      return "Você está offline — os dados continuam salvos aqui no aparelho. Reconecte para sincronizar.";
    }
    const st = e && (e.status || (e.response && e.response.status));
    if (st === 401 || st === 403) return "Sua sessão expirou — seus dados continuam aqui. Faça login novamente para enviar.";
    if (st === 413) return "O áudio excedeu o limite de tamanho. Regrave um trecho mais curto ou salve sem o áudio.";
    if (st >= 500) return "Erro no servidor. Seus dados continuam em memória — tente novamente em instantes.";
    const quota = e && (e.name === "QuotaExceededError" || e.code === 22 || e.code === 1014 || /quota|exceeded/i.test(e.message || ""));
    if (quota) return "Armazenamento local cheio — provavelmente os áudios excederam o limite do navegador. Finalize/apague avaliações antigas ou regrave trechos mais curtos.";
    return "Não foi possível salvar agora. Seus dados continuam em memória — tente novamente.";
  };

  const NAV = [
    { id: "dashboard",    label: "Dashboard",    icon: "dashboard" },
    { id: "pacientes",    label: "Pacientes",    icon: "users" },
    { id: "agenda",       label: "Agenda",       icon: "calendar" },
    { id: "atendimentos", label: "Atendimentos", icon: "clipboardCheck" },
    { id: "planejamentos",label: "Planejamentos",icon: "fileText" },
    { id: "avaliacoes",   label: "Avaliações",   icon: "clipboardList" },
    { id: "financeiro",   label: "Financeiro",   icon: "wallet" },
    { id: "biblioteca",   label: "Biblioteca",   icon: "book" },
    { id: "flashcards",   label: "Flashcards",   icon: "layers" },
  ];

  function Sidebar({ active, onNavigate, open, onClose, canInstall, onInstall, activeProf, onSelectProf, onManageTeam }) {
    return (
      <>
        <div className={"scrim" + (open ? " show" : "")} onClick={onClose}></div>
        <aside className={"sidebar" + (open ? " open" : "")}>
          <div className="sb-brand">
            <Logo size={38} />
            <div className="bk">
              <b>Educare</b>
              <span>Painel profissional</span>
            </div>
          </div>

          <div className="sb-label">MENU</div>
          <nav className="sb-nav">
            {NAV.map((n) => (
              <button
                key={n.id}
                className={"sb-item" + (active === n.id ? " active" : "")}
                onClick={() => { onNavigate(n.id); onClose && onClose(); }}
              >
                <Icon name={n.icon} size={20} />
                {n.label}
                {n.badge && <span className="sb-badge">{n.badge}</span>}
              </button>
            ))}
          </nav>

          <div className="sb-foot">
            {canInstall && (
              <button className="sb-install" onClick={onInstall}>
                <Icon name="download" size={18} /> Instalar app
              </button>
            )}
            <window.ProfSwitcher activeProf={activeProf} onSelect={onSelectProf} onManage={onManageTeam} />
            <button className={"sb-item" + (active === "configuracoes" ? " active" : "")} onClick={() => { onNavigate("configuracoes"); onClose && onClose(); }}><Icon name="settings" size={20} />Configurações</button>
            {window.EducareBilling && window.EducareBilling.ehAdmin() && (
              <button className={"sb-item" + (active === "admin" ? " active" : "")} onClick={() => { onNavigate("admin"); onClose && onClose(); }}>
                <Icon name="sparkles" size={20} />Planos das contas
              </button>
            )}
            <button className="sb-item"><Icon name="help" size={20} />Tutoriais</button>
            <button className="sb-item"><Icon name="headset" size={20} />Suporte</button>
            <button className="sb-item" onClick={() => onNavigate("__logout")}>
              <Icon name="logout" size={20} />Sair da conta
            </button>
            <p className="sb-credit" style={{ textAlign: "center", fontSize: 11.5, color: "var(--text-3)", margin: "10px 4px 4px", lineHeight: 1.4 }}>
              Desenvolvido por <b style={{ fontWeight: 700 }}>JuFlow Digital</b> © 2026
            </p>
          </div>
        </aside>
      </>
    );
  }

  const NOTIF_READ_KEY = "educare-notif-read";

  function buildNotifications() {
    const today = window.todayISO ? window.todayISO() : "2026-06-04";
    const fmt = (isoDate) => { const [y, m, d] = isoDate.split("-"); return `${d}/${m}`; };
    const out = [];

    (window.EVENTS || [])
      .filter((e) => !e.allDay && e.date >= today && (e.type === "agendado" || e.type === "confirmado"))
      .sort((a, b) => (a.date + a.start).localeCompare(b.date + b.start))
      .slice(0, 4)
      .forEach((e, i) => out.push({
        id: "ev-" + e.date + "-" + e.start + "-" + i,
        icon: "calendar", cls: "info",
        title: e.type === "confirmado" ? "Sessão confirmada" : "Sessão agendada",
        desc: `${e.title} · ${fmt(e.date)} às ${e.start}`,
        page: "agenda",
      }));

    (window.PAYMENTS || [])
      .filter((p) => p.status === "pendente" || p.status === "atrasado")
      .slice(0, 3)
      .forEach((p, i) => {
        const pac = (window.PATIENTS || []).find((x) => x.id === p.pid);
        out.push({
          id: "pay-" + p.pid + "-" + p.date + "-" + i,
          icon: "wallet", cls: p.status === "atrasado" ? "danger" : "warn",
          title: p.status === "atrasado" ? "Pagamento atrasado" : "Pagamento pendente",
          desc: `${pac ? pac.name : "Paciente"} · R$ ${p.value}`,
          page: "financeiro",
        });
      });

    (window.EVENTS || [])
      .filter((e) => e.type === "aniversario" && e.date >= today)
      .slice(0, 2)
      .forEach((e, i) => out.push({
        id: "bday-" + e.date + "-" + i,
        icon: "heart", cls: "accent",
        title: "Aniversário",
        desc: `${e.title.replace(/^Aniversário\s*[—-]\s*/, "")} · ${fmt(e.date)}`,
        page: "agenda",
      }));

    return out;
  }

  function NotificationsButton({ onNavigate }) {
    const [open, setOpen] = useState(false);
    const items = React.useMemo(() => buildNotifications(), []);
    const [readIds, setReadIds] = useState(() => {
      try { return new Set(JSON.parse(localStorage.getItem(NOTIF_READ_KEY) || "[]")); } catch (e) { return new Set(); }
    });
    const persist = (set) => { try { localStorage.setItem(NOTIF_READ_KEY, JSON.stringify([...set])); } catch (e) {} };
    const unread = items.filter((n) => !readIds.has(n.id)).length;

    function markAll() {
      const s = new Set(items.map((n) => n.id));
      setReadIds(s); persist(s);
    }
    function openItem(n) {
      const s = new Set(readIds); s.add(n.id); setReadIds(s); persist(s);
      setOpen(false);
      if (n.page) onNavigate(n.page);
    }

    return (
      <div className="notif">
        {open && <div className="notif-backdrop" onClick={() => setOpen(false)}></div>}
        <button className="top-icon" aria-label="Notificações" onClick={() => setOpen((o) => !o)}>
          <Icon name="bell" size={21} />
          {unread > 0 && <span className="dot"></span>}
        </button>
        {open && (
          <div className="notif-pop">
            <div className="notif-head">
              <b>Notificações {unread > 0 && <span className="notif-count">{unread}</span>}</b>
              {unread > 0 && <button className="link" onClick={markAll}>Marcar todas como lidas</button>}
            </div>
            <div className="notif-list">
              {items.length === 0 && <div className="notif-empty">Você está em dia! 🎉</div>}
              {items.map((n) => (
                <button key={n.id} className={"notif-item" + (readIds.has(n.id) ? "" : " unread")} onClick={() => openItem(n)}>
                  <span className={"ni-ic " + n.cls}><Icon name={n.icon} size={17} /></span>
                  <span className="ni-body">
                    <b>{n.title}</b>
                    <span>{n.desc}</span>
                  </span>
                  {!readIds.has(n.id) && <i className="ni-dot"></i>}
                </button>
              ))}
            </div>
          </div>
        )}
      </div>
    );
  }

  function TopBar({ theme, onToggleTheme, onMenu, onNavigate }) {
    return (
      <header className="topbar">
        <button className="menu-btn" onClick={onMenu} aria-label="Menu"><Icon name="menu" size={22} /></button>
        <div className="search">
          <Icon name="search" size={19} />
          <input placeholder="Buscar pacientes, planejamentos..." />
        </div>
        <NotificationsButton onNavigate={onNavigate} />
        <div className="theme-toggle" role="group" aria-label="Tema">
          <button className={theme === "light" ? "on" : ""} onClick={() => onToggleTheme("light")} aria-label="Tema claro">
            <Icon name="sun" size={19} />
          </button>
          <button className={theme === "dark" ? "on" : ""} onClick={() => onToggleTheme("dark")} aria-label="Tema escuro">
            <Icon name="moon" size={18} />
          </button>
        </div>
      </header>
    );
  }

  /* ---- Mini calendar (hoje = data local do dispositivo), navegável e com eventos ---- */
  const CAL_MON = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
  const EV_COLOR = {
    agendado: "var(--st-agendado)", confirmado: "var(--st-confirmado)", compromisso: "var(--st-compromisso)",
    bloqueado: "var(--st-bloqueado)", aniversario: "var(--st-aniversario)", feriado: "var(--st-feriado)",
    realizado: "var(--st-realizado)", falta: "var(--st-falta)",
  };
  const calIso = (dt) => `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, "0")}-${String(dt.getDate()).padStart(2, "0")}`;

  function MiniCalendar({ onPickDay }) {
    // Hoje = data LOCAL do dispositivo (ano/mês/dia) — nunca fixada nem derivada de timestamp UTC.
    const hojeLocal = () => { const n = new Date(); return new Date(n.getFullYear(), n.getMonth(), n.getDate()); };
    const [today, setToday] = useState(hojeLocal);
    const [cursor, setCursor] = useState(() => { const t = hojeLocal(); return new Date(t.getFullYear(), t.getMonth(), 1); });
    const [selected, setSelected] = useState(null); // dia selecionado manualmente (ISO)

    // Migra o destaque para o novo dia na virada da meia-noite: checagem leve por
    // minuto e também ao focar/reexibir a janela. Compara por Y/M/D locais.
    useEffect(() => {
      const check = () => { const t = hojeLocal(); setToday((prev) => (calIso(prev) !== calIso(t) ? t : prev)); };
      const id = setInterval(check, 60 * 1000);
      window.addEventListener("focus", check);
      document.addEventListener("visibilitychange", check);
      return () => { clearInterval(id); window.removeEventListener("focus", check); document.removeEventListener("visibilitychange", check); };
    }, []);

    const dow = ["DO", "SE", "TE", "QU", "QU", "SE", "SÁ"];
    const y = cursor.getFullYear(), m = cursor.getMonth();
    const leading = new Date(y, m, 1).getDay(); // grade começa no domingo
    const daysInMonth = new Date(y, m + 1, 0).getDate();
    const total = Math.ceil((leading + daysInMonth) / 7) * 7;
    const cells = Array.from({ length: total }, (_, i) => new Date(y, m, 1 - leading + i));
    const todayIso = calIso(today);
    const noMesAtual = y === today.getFullYear() && m === today.getMonth();

    const dotsFor = (isoDate) => {
      const types = [];
      (window.EVENTS || []).forEach((e) => { if (e.date === isoDate && !types.includes(e.type)) types.push(e.type); });
      return types.slice(0, 3);
    };
    const irParaHoje = () => { const t = hojeLocal(); setToday(t); setCursor(new Date(t.getFullYear(), t.getMonth(), 1)); };

    return (
      <div className="card">
        <div className="cal-head">
          <button className="cal-nav" aria-label="Mês anterior" onClick={() => setCursor(new Date(y, m - 1, 1))}><Icon name="chevL" size={18} /></button>
          <b>{CAL_MON[m]} {y}</b>
          <div style={{ display: "flex", alignItems: "center", gap: 4 }}>
            {!noMesAtual && <button className="cal-today" onClick={irParaHoje}>Hoje</button>}
            <button className="cal-nav" aria-label="Próximo mês" onClick={() => setCursor(new Date(y, m + 1, 1))}><Icon name="chevR" size={18} /></button>
          </div>
        </div>
        <div className="cal-grid">
          {dow.map((d, i) => <div className="cal-dow" key={i}>{d}</div>)}
          {cells.map((dt, i) => {
            const inMonth = dt.getMonth() === m;
            const isoDate = calIso(dt);
            const dots = dotsFor(isoDate);
            const isToday = inMonth && isoDate === todayIso;        // destaca hoje só no mês atual exibido
            const isSelected = isoDate === selected && !isToday;    // seleção manual = contorno (distinto de hoje)
            return (
              <button
                key={i}
                className={"cal-day" + (inMonth ? "" : " muted") + (isToday ? " today" : "") + (isSelected ? " selected" : "") + (dots.length ? " has-ev" : "")}
                onClick={() => { setSelected(isoDate); onPickDay && onPickDay(isoDate); }}
                aria-label={isoDate + (isToday ? " (hoje)" : "")}
                aria-current={isToday ? "date" : undefined}
              >
                {dt.getDate()}
                {dots.length > 0 && (
                  <span className="cal-evs">
                    {dots.map((t, j) => <i key={j} className="cal-evdot" style={{ background: EV_COLOR[t] }}></i>)}
                  </span>
                )}
              </button>
            );
          })}
        </div>
        <div className="legend">
          <span><i className="ld" style={{ background: "var(--st-agendado)" }}></i>Agendado</span>
          <span><i className="ld" style={{ background: "var(--st-confirmado)" }}></i>Confirmado</span>
          <span><i className="ld" style={{ background: "var(--st-realizado)" }}></i>Sessão realizada</span>
          <span><i className="ld" style={{ background: "var(--st-falta)" }}></i>Falta</span>
          <span><i className="ld" style={{ background: "var(--st-compromisso)" }}></i>Compromisso</span>
          <span><i className="ld" style={{ background: "var(--st-bloqueado)" }}></i>Bloqueado</span>
          <span><i className="ld" style={{ background: "var(--st-aniversario)" }}></i>Aniversário</span>
          <span><i className="ld" style={{ background: "var(--st-feriado)" }}></i>Feriado</span>
        </div>
      </div>
    );
  }

  const RAIL_MON = ["jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez"];

  function RightRail({ onNavigate, onSchedule, onPickDay, rail }) {
    if (rail && rail.kind === "hayling") {
      return (
        <aside className="rail">
          <div className="card card-pad">
            <div className="card-title"><span className="ct"><Icon name="clipboardList" size={18} />{rail.title}</span></div>
            <div className="hl-grid rail-legend">
              {(rail.tipos || []).map((tp) => (
                <div className="hl-card" key={tp.code}>
                  <span className="hl-code">{tp.code}</span>
                  <div className="hl-body">
                    <b>{tp.score} {tp.score === 1 ? "ponto" : "pontos"}</b>
                    {tp.desc && <span>{tp.desc}</span>}
                  </div>
                </div>
              ))}
            </div>
          </div>
        </aside>
      );
    }
    return (
      <aside className="rail">
        <MiniCalendar onPickDay={onPickDay} />

        {window.PagamentosPanel ? <window.PagamentosPanel onNavigate={onNavigate} /> : null}

        <div className="card card-pad tip">
          <div className="tlabel">SABIA QUE…</div>
          <h4>Anamnese Estruturada <Icon name="folderHeart" size={18} style={{ color: "var(--accent)" }} /></h4>
          <p>Registre o histórico completo da criança com um formulário clínico guiado, pronto para exportar em PDF.</p>
          <div className="howto">
            <b><Icon name="sparkles" size={15} style={{ color: "var(--accent-strong)" }} />Como usar</b>
            <p>Após salvar a anamnese, você pode criar um planejamento vinculado direto da página de resultado.</p>
          </div>
        </div>
      </aside>
    );
  }

  function BottomNav({ active, onNavigate, onMore }) {
    const items = [
      { id: "dashboard", label: "Início", icon: "home" },
      { id: "pacientes", label: "Pacientes", icon: "users" },
      { id: "agenda", label: "Agenda", icon: "calendar" },
      { id: "atendimentos", label: "Sessões", icon: "clipboardCheck" },
    ];
    return (
      <nav className="bottom-nav">
        {items.map((n) => (
          <button key={n.id} className={"bn-item" + (active === n.id ? " active" : "")} onClick={() => onNavigate(n.id)}>
            <Icon name={n.icon} size={22} />
            <span>{n.label}</span>
          </button>
        ))}
        <button className="bn-item" onClick={onMore}>
          <Icon name="menu" size={22} />
          <span>Mais</span>
        </button>
      </nav>
    );
  }

  function AppShell({ active, onNavigate, theme, onToggleTheme, canInstall, onInstall, activeProf, onSelectProf, onManageTeam, onSchedule, onPickDay, rail, children }) {
    const [menuOpen, setMenuOpen] = useState(false);
    return (
      <div className="app-grid">
        <Sidebar active={active} onNavigate={onNavigate} open={menuOpen} onClose={() => setMenuOpen(false)} canInstall={canInstall} onInstall={onInstall} activeProf={activeProf} onSelectProf={onSelectProf} onManageTeam={onManageTeam} />
        <div className="main-col">
          <TopBar theme={theme} onToggleTheme={onToggleTheme} onMenu={() => setMenuOpen(true)} onNavigate={onNavigate} />
          {/* Fora do main-scroll de propósito: o aviso de teste vencendo
              e o de modo leitura valem para a tela inteira e não podem
              sumir quando a pessoa rola a página. */}
          {window.FaixaDeAssinatura && <window.FaixaDeAssinatura onNavigate={onNavigate} />}
          <div className="main-scroll">{children}</div>
        </div>
        <RightRail onNavigate={onNavigate} onSchedule={onSchedule} onPickDay={onPickDay} rail={rail} />
        <BottomNav active={active} onNavigate={onNavigate} onMore={() => setMenuOpen(true)} />
      </div>
    );
  }

  window.AppShell = AppShell;
  window.NAV = NAV;
})();
