// app.jsx — Arco Rooms app shell + routing
// Built on the EstateFlow design system. Academic-year room management is
// the default; Summer is its own sidebar section.
// Adds: dark-mode toggle + EN/ES language toggle in the page header.

function App() {
  const [tw, setTweak] = useTweaks(window.TWEAK_DEFAULTS);
  const { lang, t, setLang } = useLang();

  // Keep html[lang] in sync with the active locale for a11y + SEO.
  React.useEffect(() => {
    document.documentElement.setAttribute("lang", lang === "es" ? "es" : "en");
  }, [lang]);

  // ── Theme (dark / light) — persisted in localStorage. ──────────
  const [theme, setTheme] = React.useState(() => localStorage.getItem("arco.theme") || "light");
  React.useEffect(() => {
    localStorage.setItem("arco.theme", theme);
    document.documentElement.setAttribute("data-theme", theme);
  }, [theme]);
  const toggleTheme = () => setTheme((x) => x === "dark" ? "light" : "dark");
  const toggleLang  = () => setLang(lang === "es" ? "en" : "es");

  // ── Sidebar collapsed state — persisted in localStorage. ──────────
  const [collapsed, setCollapsed] = React.useState(() => localStorage.getItem("arco.sidebar") === "collapsed");
  React.useEffect(() => { localStorage.setItem("arco.sidebar", collapsed ? "collapsed" : "expanded"); }, [collapsed]);
  const toggleCollapsed = () => setCollapsed((x) => !x);

  // ── Chat rail (Arco assistant) — persisted, default collapsed. ────
  const [chatOpen, setChatOpen] = React.useState(() => localStorage.getItem("arco.chat") === "expanded");
  React.useEffect(() => { localStorage.setItem("arco.chat", chatOpen ? "expanded" : "collapsed"); }, [chatOpen]);
  const toggleChat = () => setChatOpen((x) => !x);

  // ── Route (URL-hash backed) ──────────────────────────────────
  const parseHash = () => {
    const raw = (window.location.hash || "#dashboard").slice(1);
    const [name, ...rest] = raw.split("/");
    return { name: name || "dashboard", arg: rest.join("/") || null };
  };
  const [route, setRoute] = React.useState(parseHash);
  React.useEffect(() => {
    const onHash = () => setRoute(parseHash());
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);
  const nav = (name, arg) => { window.location.hash = arg ? `${name}/${arg}` : name; };

  // ── Layout tweaks ─────────────────────────────────────────────
  React.useEffect(() => {
    document.documentElement.setAttribute("data-density", tw.density);
  }, [tw.density]);
  React.useEffect(() => {
    document.documentElement.setAttribute("data-nav", tw.nav);
  }, [tw.nav]);

  const [addOpen, setAddOpen] = React.useState(false);
  const [toast, setToast] = React.useState(null);
  // Confirmation dialog state — populated by ctx.confirm() instead of window.confirm
  const [confirmState, setConfirmState] = React.useState(null);
  const confirm = React.useCallback((opts) => setConfirmState(opts), []);
  // showToast accepts either a string or { message, undo, ttl } so callers
  // can offer "Deshacer" actions inline. Toast component (lib.jsx) consumes
  // both shapes.
  const showToast = (m) => setToast(typeof m === "string" ? { message: m } : m);

  // ── Modal stack ──
  // Centralized so any screen can do ctx.openModal("addBill", { prefillAptId }).
  const [modals, setModals] = React.useState([]);
  const openModal = React.useCallback((name, props = {}) => {
    setModals((arr) => [...arr, { name, props, id: Math.random().toString(36).slice(2) }]);
  }, []);

  // Command palette ⌘K
  const [cmdOpen, setCmdOpen] = React.useState(false);
  React.useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault();
        setCmdOpen((x) => !x);
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  // ── Live overlay ──
  // Any user action that mutates "data" lands here as a layered override on
  // top of ArcoData so the prototype feels real without a backing store.
  const [overlay, setOverlay] = React.useState({
    paid: {},
    ticketStatus: {},
    newTenants: [],
    newBookings: [],
    newBills: [],
    newExpenses: [],
    newTickets: [],
    newApartments: [],
    tenantEdits: {},
    bookingEdits: {},
    removedApartments: {},
  });

  const markPaid = (billId, opts = {}) => {
    setOverlay((o) => ({ ...o, paid: { ...o.paid, [billId]: true } }));
    // opts may include { method, amount } from the confirm popover.
    const methodLabel = opts.method ? t(`mp.method.${opts.method}`) : null;
    const message = methodLabel && opts.amount != null
      ? t("toast.paidUndo", { method: methodLabel.toLowerCase(), amt: opts.amount })
      : t("toast.paid");
    showToast({
      message,
      undo: () => {
        setOverlay((o) => {
          const next = { ...o.paid };
          delete next[billId];
          return { ...o, paid: next };
        });
        showToast(t("toast.undone"));
      },
    });
  };
  const setTicket = (ticketId, status) => {
    setOverlay((o) => ({ ...o, ticketStatus: { ...o.ticketStatus, [ticketId]: status } }));
    const stateLabel = status === "in-progress" ? t("st.inProgress").toLowerCase() : t(`st.${status}`).toLowerCase();
    showToast(t("toast.moved", { state: stateLabel }));
  };
  const addTenant = (tenant) => {
    setOverlay((o) => ({ ...o, newTenants: [...o.newTenants, tenant] }));
    showToast(t("toast.added", { name: tenant.name, apt: ArcoData.byId.apt(tenant.aptId)?.name }));
  };
  const addBill = (bill) => {
    setOverlay((o) => ({ ...o, newBills: [...o.newBills, bill] }));
    showToast(`${bill.label} · ${bill.amount} € añadido`);
  };
  const addExpense = (expense) => {
    setOverlay((o) => ({ ...o, newExpenses: [...o.newExpenses, expense] }));
    showToast(`Gasto registrado · −${expense.amount} €`);
  };
  const addBooking = (booking) => {
    setOverlay((o) => ({ ...o, newBookings: [...o.newBookings, booking] }));
    showToast(`Reserva ${booking.status === "confirmed" ? "confirmada" : "retenida"} · ${booking.guestName}`);
  };
  const updateBooking = (bookingId, patch) => {
    setOverlay((o) => ({ ...o, bookingEdits: { ...(o.bookingEdits || {}), [bookingId]: { ...((o.bookingEdits || {})[bookingId] || {}), ...patch } } }));
    showToast("Reserva actualizada");
  };
  const addTicket = (ticket) => {
    setOverlay((o) => ({ ...o, newTickets: [...o.newTickets, ticket] }));
    showToast(`Incidencia abierta: ${ticket.title}`);
  };
  const addApartment = (apt) => {
    setOverlay((o) => ({ ...o, newApartments: [...o.newApartments, apt] }));
    if (ArcoData.aptYTD) ArcoData.aptYTD[apt.id] = { revenue: 0, expenses: 0, mortgage: 0, net: 0 };
    showToast(`Piso "${apt.name}" añadido`);
  };
  const removeApartment = (aptId) => {
    const apt = ArcoData.byId.apt(aptId) || overlay.newApartments.find((a) => a.id === aptId);
    setOverlay((o) => ({ ...o, removedApartments: { ...o.removedApartments, [aptId]: true } }));
    showToast(`Piso "${apt?.name || aptId}" eliminado`);
    if (route.name === "apartment" && route.arg === aptId) nav("apartments");
  };
  const updateTenant = (tenantId, patch) => {
    setOverlay((o) => ({ ...o, tenantEdits: { ...o.tenantEdits, [tenantId]: { ...(o.tenantEdits[tenantId] || {}), ...patch } } }));
    showToast("Contrato actualizado");
  };

  // Effective data with overlay applied
  const data = React.useMemo(() => {
    const bills = [
      ...ArcoData.bills.map((b) => overlay.paid[b.id]
        ? { ...b, status: "paid", paidOn: ArcoData.ISO(ArcoData.today) } : b),
      ...overlay.newBills,
    ];
    const tickets = [
      ...ArcoData.tickets.map((tt) => overlay.ticketStatus[tt.id]
        ? { ...tt, status: overlay.ticketStatus[tt.id], closedAt: overlay.ticketStatus[tt.id] === "resolved" ? ArcoData.ISO(ArcoData.today) : tt.closedAt } : tt),
      ...overlay.newTickets,
    ];
    const tenants = [...ArcoData.tenants, ...overlay.newTenants].map((tn) =>
      overlay.tenantEdits[tn.id] ? { ...tn, ...overlay.tenantEdits[tn.id] } : tn);
    const bookings = [...(ArcoData.bookings || []), ...overlay.newBookings].map((bk) =>
      (overlay.bookingEdits || {})[bk.id] ? { ...bk, ...overlay.bookingEdits[bk.id] } : bk);
    const expenses = [...(ArcoData.expenses || []), ...overlay.newExpenses];
    const apartments = [...ArcoData.apartments, ...overlay.newApartments]
      .filter((a) => !overlay.removedApartments[a.id]);
    return {
      ...ArcoData, bills, tickets, tenants, bookings, expenses, apartments,
      byId: {
        apt: (id) => apartments.find((a) => a.id === id),
        tenant: (id) => tenants.find((tn) => tn.id === id),
      },
    };
  }, [overlay]);

  const ctx = { route, nav, t: tw, setTweak, data,
                markPaid, setTicket, addTenant,
                addBill, addExpense, addBooking, updateBooking, addTicket,
                addApartment, removeApartment, updateTenant,
                openModal,
                openAddTenant: () => openModal("addTenant"),
                showToast,
                openCommandPalette: () => setCmdOpen(true),
                // i18n + theme helpers, available on every screen
                tt: t, lang, theme, toggleTheme, toggleLang,
                // Chat rail toggle so AICard CTA can expand the rail.
                chatOpen, toggleChat,
                // Confirmation dialog — call ctx.confirm({ title, body, confirmLabel, danger, onConfirm })
                confirm };

  // Dispatch modal name → component
  const renderModal = (m) => {
    const close = () => setModals((arr) => arr.filter((x) => x.id !== m.id));
    const common = { ctx, onClose: close };
    switch (m.name) {
      case "addTenant":     return <AddTenantModal {...common} {...m.props} onCreate={(tn) => { addTenant(tn); close(); }} />;
      case "addBill":       return <AddBillModal {...common} {...m.props} />;
      case "addExpense":    return <AddExpenseModal {...common} {...m.props} />;
      case "newBooking":    return <NewBookingModal {...common} {...m.props} />;
      case "newTicket":     return <NewTicketModal {...common} {...m.props} />;
      case "newApartment":  return <NewApartmentModal {...common} {...m.props} />;
      case "editTenant":    return <EditTenantModal {...common} {...m.props} />;
      case "bookingDetail": return <BookingDetailModal {...common} {...m.props} />;
      default:              return null;
    }
  };

  const openTickets   = data.tickets.filter((x) => x.status !== "resolved").length;
  const unreadConvs   = data.conversations.filter((c) => c.unread > 0).length;
  const overdueBills  = data.bills.filter((b) => b.status === "overdue" || b.status === "pending").length;
  const todayISO      = ArcoData.ISO(ArcoData.today);
  const upcomingSummer = data.bookings.filter((b) =>
    b.status !== "blocked" && b.status !== "resident" &&
    b.start >= todayISO && b.start <= "2026-09-01").length;

  const workspace = [
    { id: "dashboard",   labelKey: "nav.dashboard",   icon: "dashboard" },
    { id: "apartments",  labelKey: "nav.apartments",  icon: "building", count: data.apartments.length },
    { id: "tenants",     labelKey: "nav.tenants",     icon: "users",    count: data.tenants.filter((tn) => tn.status === "active").length },
    { id: "income",      labelKey: "nav.income",      icon: "upTrend",  count: overdueBills || undefined },
    { id: "expenses",    labelKey: "nav.expenses",    icon: "receipt" },
    { id: "maintenance", labelKey: "nav.maintenance", icon: "wrench",   count: openTickets || undefined },
    { id: "messages",    labelKey: "nav.messages",    icon: "chat",     count: unreadConvs || undefined },
  ];

  const navOf = (routeName) => ({ apartment: "apartments", tenant: "tenants" })[routeName] || routeName;
  const isCurrent = (id) => navOf(route.name) === id;

  const renderScreen = () => {
    switch (route.name) {
      case "dashboard":    return <Dashboard ctx={ctx} />;
      case "apartments":   return <Apartments ctx={ctx} />;
      case "apartment":    return <ApartmentDetail ctx={ctx} aptId={route.arg} />;
      case "tenants":      return <TenantsList ctx={ctx} />;
      case "tenant":       return <TenantDetail ctx={ctx} tenantId={route.arg} />;
      case "summer":       return <SummerSection ctx={ctx} initialTab={route.arg} />;
      case "finances":     return <Finances ctx={ctx} />;
      case "income":       return <Finances ctx={ctx} initialTab="bills" />;
      case "expenses":     return <Finances ctx={ctx} initialTab="expenses" />;
      case "maintenance":  return <Maintenance ctx={ctx} />;
      case "messages":     return <Messages ctx={ctx} initialId={route.arg} />;
      case "settings":     return <Settings ctx={ctx} />;
      default:             return <Dashboard ctx={ctx} />;
    }
  };

  const Brand = (
    <div className="brand flex center gap-2" style={{ minWidth: 0 }}>
      <BrandMark size={26} />
      <div className="wordmark" style={{ minWidth: 0, lineHeight: 1.1 }}>
        <div style={{ fontFamily: "var(--ef-font-display)", fontWeight: 600, fontSize: 17, color: "var(--ef-ink)", letterSpacing: "-0.01em" }}>
          Arco Rooms
        </div>
        <div style={{ fontSize: 10.5, fontWeight: 500, color: "var(--ef-muted)", letterSpacing: "0.06em", textTransform: "uppercase", marginTop: 2 }}>
          del Arco · Madrid
        </div>
      </div>
    </div>
  );

  const Sidebar = (
    <aside className="sidebar">
      <div className="sidebar-head">
        {Brand}
        <button className="sidebar-collapse" onClick={toggleCollapsed}
                aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"}
                title={collapsed ? "Expand sidebar" : "Collapse sidebar"}>
          <Icon name={collapsed ? "panelOpen" : "panelClose"} size={16} />
        </button>
      </div>
      <nav className="nav">
        <div className="nav-group-label">{t("nav.workspace")}</div>
        {workspace.map((it) => (
          <button key={it.id} className="nav-item"
                  aria-current={isCurrent(it.id)}
                  title={collapsed ? t(it.labelKey) : undefined}
                  onClick={() => nav(it.id)}>
            <Icon name={it.icon} size={16} />
            <span>{t(it.labelKey)}</span>
            {it.count != null && <span className="count">{it.count}</span>}
          </button>
        ))}

        <div className="nav-group-label">{t("nav.shortStay")}</div>
        <button className="nav-item summer-nav-item"
                aria-current={isCurrent("summer")}
                title={collapsed ? t("nav.summer") : undefined}
                onClick={() => nav("summer")}>
          <Icon name="sun" size={16} />
          <span>{t("nav.summer")}</span>
          {upcomingSummer > 0
            ? <span className="count">{upcomingSummer}</span>
            : <span className="accent-dot" title="Summer is live" />}
        </button>

        <div className="nav-group-label">{t("nav.quick")}</div>
        <button className="nav-item" onClick={() => setAddOpen(true)}
                title={collapsed ? t("nav.addTenant") : undefined}>
          <Icon name="plus" size={16} />
          <span>{t("nav.addTenant")}</span>
        </button>
        <button className="nav-item" onClick={() => nav("finances")}
                title={collapsed ? t("nav.recordExpense") : undefined}>
          <Icon name="receipt" size={16} />
          <span>{t("nav.recordExpense")}</span>
        </button>
        <button className="nav-item"
                aria-current={isCurrent("settings")}
                onClick={() => nav("settings")}
                title={collapsed ? t("nav.settings") : undefined}>
          <Icon name="settings" size={16} />
          <span>{t("nav.settings")}</span>
        </button>
      </nav>
      <div className="sidebar-foot">
        <UserMenu ctx={ctx} align="right" trigger={
          <button className="sidebar-user-trigger" aria-label={t("ui.userMenu") || "Menú de usuario"}>
            <Avatar name="Sergio del Arco" accent />
            <div className="who">
              <b>Sergio del Arco</b>
              <span>{t("nav.owner")} · {data.apartments.length} {t("nav.flats")}</span>
            </div>
            <span className="sidebar-user-chev"><Icon name="chevU" size={12} /></span>
          </button>
        } />
      </div>
    </aside>
  );

  const TopNav = (
    <header className="topnav">
      {Brand}
      <nav className="nav">
        {workspace.map((it) => (
          <button key={it.id} className="nav-item"
                  aria-current={isCurrent(it.id)}
                  onClick={() => nav(it.id)}>
            <Icon name={it.icon} size={15} />
            <span>{t(it.labelKey)}</span>
            {it.count != null && <span className="count">{it.count}</span>}
          </button>
        ))}
        <button className="nav-item summer-nav-item"
                aria-current={isCurrent("summer")}
                onClick={() => nav("summer")}>
          <Icon name="sun" size={15} />
          <span>{t("nav.summer")}</span>
          {upcomingSummer > 0 && <span className="count">{upcomingSummer}</span>}
        </button>
      </nav>
      <div style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: 10 }}>
        <ToolbarBar theme={theme} lang={lang} toggleTheme={toggleTheme} toggleLang={toggleLang} t={t} ctx={ctx} />
        <UserMenu ctx={ctx} align="right" trigger={
          <button className="iconbtn sm" aria-label="Perfil" style={{ padding: 0, border: 0 }}>
            <Avatar name="Sergio del Arco" accent size="sm" />
          </button>
        } />
      </div>
    </header>
  );

  return (
    <>
      <div className="app" data-nav={tw.nav} data-listings={tw.listings}
           data-sidebar={collapsed ? "collapsed" : "expanded"}
           data-chat={chatOpen ? "expanded" : "collapsed"}>
        {tw.nav === "sidebar" ? Sidebar : TopNav}
        <main className="main">{renderScreen()}</main>
        <ChatRail ctx={ctx} expanded={chatOpen} onToggle={toggleChat} />
      </div>

      {modals.map((m) => <React.Fragment key={m.id}>{renderModal(m)}</React.Fragment>)}

      {confirmState && (
        <ConfirmDialog
          title={confirmState.title}
          body={confirmState.body}
          confirmLabel={confirmState.confirmLabel}
          cancelLabel={confirmState.cancelLabel}
          danger={confirmState.danger}
          onConfirm={() => { const c = confirmState; setConfirmState(null); c.onConfirm && c.onConfirm(); }}
          onCancel={() => { const c = confirmState; setConfirmState(null); c.onCancel && c.onCancel(); }}
        />
      )}

      {toast && <Toast {...toast} onDone={() => setToast(null)} />}

      <CommandPalette ctx={ctx} open={cmdOpen} onClose={() => setCmdOpen(false)} />

      <TweaksPanel title="Arco · Tweaks">
        <TweakSection label="Layout" />
        <TweakRadio label="Navigation" value={tw.nav}
                    options={[{ value: "sidebar", label: "Sidebar" }, { value: "top", label: "Top nav" }]}
                    onChange={(v) => setTweak("nav", v)} />
        <TweakRadio label="Listings" value={tw.listings}
                    options={[{ value: "cards", label: "Cards" }, { value: "table", label: "Table" }]}
                    onChange={(v) => setTweak("listings", v)} />
        <TweakRadio label="Density" value={tw.density}
                    options={[{ value: "compact", label: "Compact" }, { value: "comfortable", label: "Comfy" }]}
                    onChange={(v) => setTweak("density", v)} />
      </TweaksPanel>
    </>
  );
}

// ───────────────────────── Toolbar ─────────────────────────
// Theme + language toggles. Lives in the page header (sidebar layout)
// AND in the topnav layout. Exported so the screens can also render it
// inline next to their own action buttons.
function ToolbarBar({ theme, lang, toggleTheme, toggleLang, t, ctx, withNotif = true, withSettings = false }) {
  return (
    <div className="flex center gap-2">
      <button className="iconbtn sm" aria-label={t("ui.changeLang")} onClick={toggleLang} title={t("ui.changeLang")}>
        <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: "0.04em", fontFamily: "var(--ef-font-display)" }}>
          {lang.toUpperCase()}
        </span>
      </button>
      <button className="iconbtn sm" aria-label={t("ui.toggleDark")} onClick={toggleTheme} title={t("ui.toggleDark")}>
        <Icon name={theme === "dark" ? "sun" : "moon"} size={14} />
      </button>
      {withNotif && ctx && <NotificationsDropdown ctx={ctx} />}
      {withNotif && !ctx && <button className="iconbtn sm" aria-label={t("ui.notifications")}><Icon name="bell" size={14} /></button>}
      {withSettings && <button className="iconbtn sm" aria-label={t("ui.settings")}><Icon name="settings" size={14} /></button>}
    </div>
  );
}

window.ToolbarBar = ToolbarBar;

// Shortcut: renders the page-level header tools (lang toggle, theme toggle, bell)
// using the current ctx. Use inside any screen's .actions block.
function HeaderTools({ ctx }) {
  return <ToolbarBar
           theme={ctx.theme} lang={ctx.lang}
           toggleTheme={ctx.toggleTheme} toggleLang={ctx.toggleLang}
           t={ctx.tt} ctx={ctx} />;
}
window.HeaderTools = HeaderTools;

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
