import { useState, useEffect, useCallback, useMemo } from "react";

// ─── Utility helpers ───
const fmt = (d) => d ? new Date(d).toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" }) : "—";
const currency = (n) => `AED ${Number(n || 0).toFixed(0)}`;
const today = () => new Date().toISOString().slice(0, 10);

// ─── API client (talks to Cloudflare Worker) ───
const API = "https://tiny-math-cd55.lingvemulo.workers.dev";

const api = {
  token: null,

  async request(method, path, body) {
    const res = await fetch(`${API}${path}`, {
      method,
      headers: {
        "Content-Type": "application/json",
        ...(api.token ? { Authorization: `Bearer ${api.token}` } : {}),
      },
      ...(body ? { body: JSON.stringify(body) } : {}),
    });
    const data = await res.json();
    if (!res.ok) throw new Error(data.error || "Request failed");
    return data;
  },

  get: (path) => api.request("GET", path),
  post: (path, body) => api.request("POST", path, body),
  patch: (path, body) => api.request("PATCH", path, body),
};

// ─── Session storage (device only — stores JWT token) ───
const session = {
  get: () => { try { return JSON.parse(localStorage.getItem("lm-session")); } catch { return null; } },
  set: (v) => { try { localStorage.setItem("lm-session", JSON.stringify(v)); } catch {} },
  clear: () => { try { localStorage.removeItem("lm-session"); } catch {} },
};

// ─── Responsive hook ───
function useIsMobile(bp = 640) {
  const [m, setM] = useState(window.innerWidth < bp);
  useEffect(() => { const h = () => setM(window.innerWidth < bp); window.addEventListener("resize", h); return () => window.removeEventListener("resize", h); }, [bp]);
  return m;
}

// ─── Design tokens ───
const T = {
  bg: "#FAFAF8", surface: "#FFFFFF", surfaceAlt: "#F5F4F0",
  border: "#E8E6E1", borderFocus: "#2D2A26",
  text: "#2D2A26", textMuted: "#8A857D", textLight: "#B5B0A8",
  accent: "#3D6B5E", accentLight: "#E8F0EC", accentDark: "#2A4D42",
  warn: "#C4553A", warnLight: "#FDF0ED",
  radius: "8px", radiusLg: "12px",
  shadow: "0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)",
  shadowLg: "0 4px 12px rgba(0,0,0,0.08)",
  font: "'DM Sans', 'Helvetica Neue', sans-serif",
  fontMono: "'JetBrains Mono', 'SF Mono', monospace",
};

const baseBtn = {
  fontFamily: T.font, fontSize: "13px", fontWeight: 500, border: "none", borderRadius: T.radius,
  cursor: "pointer", padding: "8px 16px", transition: "all 0.15s ease",
  display: "inline-flex", alignItems: "center", gap: "6px", whiteSpace: "nowrap",
};
const styles = {
  btnPrimary: { ...baseBtn, background: T.accent, color: "#fff" },
  btnSecondary: { ...baseBtn, background: T.surfaceAlt, color: T.text, border: `1px solid ${T.border}` },
  btnGhost: { ...baseBtn, background: "transparent", color: T.textMuted, padding: "6px 10px" },
  input: {
    fontFamily: T.font, fontSize: "14px", padding: "9px 12px", border: `1px solid ${T.border}`,
    borderRadius: T.radius, background: T.surface, color: T.text, width: "100%", boxSizing: "border-box",
    outline: "none", transition: "border-color 0.15s",
  },
  label: { fontSize: "12px", fontWeight: 600, color: T.textMuted, textTransform: "uppercase", letterSpacing: "0.5px", marginBottom: "4px", display: "block" },
  card: { background: T.surface, borderRadius: T.radiusLg, border: `1px solid ${T.border}`, padding: "16px", boxShadow: T.shadow },
  badge: (color = T.accent, bg = T.accentLight) => ({
    fontSize: "11px", fontWeight: 600, padding: "3px 8px", borderRadius: "99px",
    background: bg, color, display: "inline-block", letterSpacing: "0.3px",
  }),
};

// ─── Icons ───
const Icon = ({ d, size = 18, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d={d} /></svg>
);
const Icons = {
  users: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75",
  calendar: "M19 4H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zM16 2v4M8 2v4M3 10h18",
  dollar: "M12 1v22M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6",
  package: "M16.5 9.4l-9-5.19M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zM3.27 6.96L12 12.01l8.73-5.05M12 22.08V12",
  home: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
  plus: "M12 5v14M5 12h14",
  x: "M18 6L6 18M6 6l12 12",
  logout: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9",
  edit: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z",
  menu: "M3 12h18M3 6h18M3 18h18",
};

// ─── Reusable Components ───
const Modal = ({ open, onClose, title, children }) => {
  if (!open) return null;
  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 1000, display: "flex", alignItems: "flex-end", justifyContent: "center", background: "rgba(0,0,0,0.3)", backdropFilter: "blur(2px)" }} onClick={onClose}>
      <div onClick={e => e.stopPropagation()} style={{
        ...styles.card, width: "100%", maxWidth: "560px", maxHeight: "90vh", overflow: "auto",
        boxShadow: T.shadowLg, animation: "slideUp 0.2s ease",
        borderBottomLeftRadius: 0, borderBottomRightRadius: 0, padding: "20px",
      }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "16px" }}>
          <h3 style={{ margin: 0, fontSize: "16px", fontWeight: 600, color: T.text }}>{title}</h3>
          <button onClick={onClose} style={{ ...styles.btnGhost, padding: "4px" }}><Icon d={Icons.x} size={18} /></button>
        </div>
        {children}
      </div>
    </div>
  );
};

const Field = ({ label, children }) => (
  <div style={{ marginBottom: "14px" }}>
    <label style={styles.label}>{label}</label>
    {children}
  </div>
);

const Input = (props) => <input {...props} style={{ ...styles.input, ...(props.style || {}) }} />;
const Select = ({ children, ...props }) => <select {...props} style={{ ...styles.input, ...(props.style || {}) }}>{children}</select>;

const Stat = ({ label, value, sub, color }) => (
  <div style={{ ...styles.card, padding: "14px", flex: "1 1 0", minWidth: 0 }}>
    <div style={{ ...styles.label, fontSize: "11px" }}>{label}</div>
    <div style={{ fontSize: "20px", fontWeight: 700, color: color || T.text, marginTop: "2px", fontFamily: T.fontMono, overflow: "hidden", textOverflow: "ellipsis" }}>{value}</div>
    {sub && <div style={{ fontSize: "11px", color: T.textMuted, marginTop: "1px" }}>{sub}</div>}
  </div>
);

const EmptyState = ({ icon, message }) => (
  <div style={{ textAlign: "center", padding: "32px 16px", color: T.textMuted }}>
    <Icon d={icon} size={28} color={T.textLight} />
    <p style={{ marginTop: "10px", fontSize: "13px" }}>{message}</p>
  </div>
);

const ListCard = ({ children, onClick }) => (
  <div onClick={onClick} style={{ ...styles.card, padding: "12px 14px", marginBottom: "8px", cursor: onClick ? "pointer" : "default" }}>
    {children}
  </div>
);

const Row = ({ left, right, bold }) => (
  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: "8px" }}>
    <span style={{ fontWeight: bold ? 600 : 400, fontSize: "13px", color: T.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0, flex: 1 }}>{left}</span>
    <span style={{ fontSize: "13px", flexShrink: 0 }}>{right}</span>
  </div>
);

const FormGrid = ({ children }) => <div className="form-grid">{children}</div>;

const ErrBanner = ({ msg }) => msg ? (
  <div style={{ background: T.warnLight, color: T.warn, border: `1px solid ${T.warn}`, borderRadius: T.radius, padding: "10px 14px", fontSize: "13px", marginBottom: "12px" }}>{msg}</div>
) : null;

const GlobalStyles = () => (
  <style>{`
    @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
    @keyframes slideUp { from { opacity: 0; transform: translateY(40px); } to { opacity: 1; transform: translateY(0); } }
    input:focus, select:focus { border-color: ${T.borderFocus} !important; }
    ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-thumb { background: ${T.border}; border-radius: 3px; }
    * { box-sizing: border-box; }
    .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
    @media (max-width: 560px) { .form-grid { grid-template-columns: 1fr; } }
    .stat-row { display: flex; gap: 10px; }
    @media (max-width: 480px) { .stat-row { flex-wrap: wrap; } .stat-row > div { flex: 1 1 calc(50% - 5px) !important; min-width: calc(50% - 5px) !important; } }
  `}</style>
);

// ═══════════════════════════════════════════════
// MAIN APP
// ═══════════════════════════════════════════════
export default function App() {
  const [loading, setLoading] = useState(true);
  const [user, setUser] = useState(null);
  const [data, setData] = useState({ users: [], students: [], packages: [], purchases: [], lessons: [] });
  const [initErr, setInitErr] = useState("");

  const loadData = useCallback(async () => {
    try {
      const d = await api.get("/data");
      setData(d);
    } catch (e) {
      setInitErr("Could not load data: " + e.message);
    }
  }, []);

  useEffect(() => {
    (async () => {
      const s = session.get();
      if (s?.token && s?.user) {
        api.token = s.token;
        setUser(s.user);
        await loadData();
      }
      setLoading(false);
    })();
  }, [loadData]);

  const login = async (email, password) => {
    try {
      const { token, user: u } = await api.post("/auth/login", { email, password });
      api.token = token;
      session.set({ token, user: u });
      setUser(u);
      await loadData();
      return true;
    } catch {
      return false;
    }
  };

  const logout = () => {
    api.token = null;
    session.clear();
    setUser(null);
    setData({ users: [], students: [], packages: [], purchases: [], lessons: [] });
  };

  const register = async (name, email, password) => {
    try {
      const { token, user: u } = await api.post("/auth/register", { name, email, password });
      api.token = token;
      session.set({ token, user: u });
      setUser(u);
      await loadData();
      return null;
    } catch (e) {
      return e.message;
    }
  };

  const reload = useCallback(() => loadData(), [loadData]);

  if (loading) return (
    <div style={{ fontFamily: T.font, display: "flex", alignItems: "center", justifyContent: "center", height: "100vh", background: T.bg, color: T.textMuted }}>
      Loading…
    </div>
  );

  if (initErr) return (
    <div style={{ fontFamily: T.font, display: "flex", alignItems: "center", justifyContent: "center", height: "100vh", background: T.bg, padding: "24px" }}>
      <div style={{ ...styles.card, maxWidth: "400px", color: T.warn }}>{initErr}</div>
    </div>
  );

  if (!user) return <LoginScreen onLogin={login} onRegister={register} />;
  if (user.role === "admin") return <AdminDashboard data={data} reload={reload} user={user} onLogout={logout} />;
  return <ClientDashboard data={data} user={user} onLogout={logout} />;
}

// ═══════════════════════════════════════════════
// LOGIN
// ═══════════════════════════════════════════════
function LoginScreen({ onLogin, onRegister }) {
  const [mode, setMode] = useState("login");
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [pw, setPw] = useState("");
  const [pw2, setPw2] = useState("");
  const [error, setError] = useState("");
  const [busy, setBusy] = useState(false);
  const switchMode = () => { setMode(m => m === "login" ? "register" : "login"); setError(""); };

  const submitLogin = async (e) => {
    e.preventDefault(); setBusy(true); setError("");
    const ok = await onLogin(email, pw);
    if (!ok) { setError("Invalid credentials"); setBusy(false); }
  };
  const submitRegister = async (e) => {
    e.preventDefault();
    if (pw !== pw2) { setError("Passwords don't match"); return; }
    if (pw.length < 4) { setError("Password must be at least 4 characters"); return; }
    setBusy(true); setError("");
    const err = await onRegister(name, email, pw);
    if (err) { setError(err); setBusy(false); }
  };

  return (
    <div style={{ fontFamily: T.font, minHeight: "100vh", background: T.bg, display: "flex", alignItems: "center", justifyContent: "center", padding: "16px" }}>
      <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
      <div style={{ ...styles.card, width: "360px", maxWidth: "100%" }}>
        <div style={{ textAlign: "center", marginBottom: "24px" }}>
          <div style={{ fontSize: "26px", fontWeight: 700, color: T.text, letterSpacing: "-0.5px" }}>Lessons</div>
          <div style={{ fontSize: "13px", color: T.textMuted, marginTop: "4px" }}>{mode === "login" ? "Sign in to your account" : "Create your account"}</div>
        </div>
        {mode === "login" ? (
          <form onSubmit={submitLogin}>
            <Field label="Email / Username"><Input value={email} onChange={e => setEmail(e.target.value)} placeholder="your@email.com" autoFocus /></Field>
            <Field label="Password"><Input type="password" value={pw} onChange={e => setPw(e.target.value)} placeholder="••••••••" /></Field>
            {error && <div style={{ color: T.warn, fontSize: "13px", marginBottom: "12px" }}>{error}</div>}
            <button type="submit" disabled={busy} style={{ ...styles.btnPrimary, width: "100%", justifyContent: "center", padding: "10px" }}>{busy ? "Signing in…" : "Sign in"}</button>
          </form>
        ) : (
          <form onSubmit={submitRegister}>
            <Field label="Full Name"><Input value={name} onChange={e => setName(e.target.value)} placeholder="Jane Smith" autoFocus /></Field>
            <Field label="Email"><Input value={email} onChange={e => setEmail(e.target.value)} placeholder="your@email.com" /></Field>
            <Field label="Password"><Input type="password" value={pw} onChange={e => setPw(e.target.value)} placeholder="••••••••" /></Field>
            <Field label="Confirm Password"><Input type="password" value={pw2} onChange={e => setPw2(e.target.value)} placeholder="••••••••" /></Field>
            {error && <div style={{ color: T.warn, fontSize: "13px", marginBottom: "12px" }}>{error}</div>}
            <button type="submit" disabled={busy || !name || !email || !pw} style={{ ...styles.btnPrimary, width: "100%", justifyContent: "center", padding: "10px", opacity: (!name || !email || !pw) ? 0.5 : 1 }}>{busy ? "Creating account…" : "Create account"}</button>
          </form>
        )}
        <div style={{ textAlign: "center", marginTop: "14px", fontSize: "13px", color: T.textMuted }}>
          {mode === "login"
            ? <>Don't have an account? <button onClick={switchMode} style={{ background: "none", border: "none", color: T.accent, cursor: "pointer", fontFamily: T.font, fontSize: "13px", fontWeight: 600, padding: 0 }}>Register</button></>
            : <>Already have an account? <button onClick={switchMode} style={{ background: "none", border: "none", color: T.accent, cursor: "pointer", fontFamily: T.font, fontSize: "13px", fontWeight: 600, padding: 0 }}>Sign in</button></>
          }
        </div>
        {mode === "login" && <div style={{ fontSize: "11px", color: T.textLight, textAlign: "center", marginTop: "10px" }}>Admin: admin / admin123</div>}
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════
// ADMIN DASHBOARD
// ═══════════════════════════════════════════════
function AdminDashboard({ data, reload, user, onLogout }) {
  const [tab, setTab] = useState("overview");
  const mobile = useIsMobile();
  const [menuOpen, setMenuOpen] = useState(false);

  const tabs = [
    { id: "overview", label: "Overview", icon: Icons.home },
    { id: "students", label: "Students", icon: Icons.users },
    { id: "lessons", label: "Lessons", icon: Icons.calendar },
    { id: "packages", label: "Packages", icon: Icons.package },
    { id: "payments", label: "Payments", icon: Icons.dollar },
  ];

  const selectTab = (id) => { setTab(id); setMenuOpen(false); };

  return (
    <div style={{ fontFamily: T.font, minHeight: "100vh", background: T.bg, color: T.text }}>
      <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
      <GlobalStyles />

      <header style={{ background: T.surface, borderBottom: `1px solid ${T.border}`, padding: "0 16px", display: "flex", alignItems: "center", justifyContent: "space-between", height: "52px", position: "sticky", top: 0, zIndex: 100 }}>
        <div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
          {mobile && <button onClick={() => setMenuOpen(!menuOpen)} style={{ ...styles.btnGhost, padding: "4px" }}><Icon d={Icons.menu} size={20} /></button>}
          <span style={{ fontSize: "17px", fontWeight: 700, letterSpacing: "-0.5px" }}>Lessons</span>
        </div>
        {!mobile && (
          <nav style={{ display: "flex", gap: "2px" }}>
            {tabs.map(t => (
              <button key={t.id} onClick={() => selectTab(t.id)}
                style={{ ...baseBtn, background: tab === t.id ? T.accentLight : "transparent", color: tab === t.id ? T.accent : T.textMuted, fontSize: "13px", padding: "6px 12px", borderRadius: "6px", fontWeight: tab === t.id ? 600 : 500 }}>
                <Icon d={t.icon} size={15} /> {t.label}
              </button>
            ))}
          </nav>
        )}
        <button onClick={onLogout} style={styles.btnGhost}><Icon d={Icons.logout} size={16} />{!mobile && " Sign out"}</button>
      </header>

      {mobile && menuOpen && (
        <div style={{ background: T.surface, borderBottom: `1px solid ${T.border}`, padding: "4px 8px 8px", position: "sticky", top: "52px", zIndex: 99 }}>
          {tabs.map(t => (
            <button key={t.id} onClick={() => selectTab(t.id)}
              style={{ ...baseBtn, width: "100%", justifyContent: "flex-start", background: tab === t.id ? T.accentLight : "transparent", color: tab === t.id ? T.accent : T.textMuted, padding: "10px 12px", borderRadius: "6px", fontWeight: tab === t.id ? 600 : 500, marginBottom: "2px" }}>
              <Icon d={t.icon} size={16} /> {t.label}
            </button>
          ))}
        </div>
      )}

      <main style={{ maxWidth: "1100px", margin: "0 auto", padding: mobile ? "16px" : "24px" }}>
        {tab === "overview" && <AdminOverview data={data} setTab={selectTab} />}
        {tab === "students" && <AdminStudents data={data} reload={reload} />}
        {tab === "lessons" && <AdminLessons data={data} reload={reload} />}
        {tab === "packages" && <AdminPackages data={data} reload={reload} />}
        {tab === "payments" && <AdminPayments data={data} reload={reload} />}
      </main>
    </div>
  );
}

// ─── Admin: Overview ───
function AdminOverview({ data, setTab }) {
  const activeStudents = data.students.filter(s => s.active !== false).length;
  const thisMonth = data.lessons.filter(l => l.date?.startsWith(new Date().toISOString().slice(0, 7)));
  const monthRevenue = data.purchases.filter(p => p.date?.startsWith(new Date().toISOString().slice(0, 7))).reduce((s, p) => s + (p.paid || 0), 0);
  const totalCredits = data.students.reduce((s, st) => {
    const bought = data.purchases.filter(p => p.student_id === st.id).reduce((a, p) => a + (p.sessions || 0), 0);
    const used = data.lessons.filter(l => l.student_ids?.includes(st.id) && l.status !== "cancelled").length;
    return s + Math.max(0, bought - used);
  }, 0);

  return (
    <div style={{ animation: "fadeIn 0.2s ease" }}>
      <h2 style={{ fontSize: "18px", fontWeight: 700, margin: "0 0 16px" }}>Dashboard</h2>
      <div className="stat-row" style={{ marginBottom: "20px" }}>
        <Stat label="Students" value={activeStudents} />
        <Stat label="This Month" value={thisMonth.length} sub="lessons" />
        <Stat label="Revenue" value={currency(monthRevenue)} sub="this month" color={T.accent} />
        <Stat label="Credits Out" value={totalCredits} sub="sessions" />
      </div>
      <div style={styles.card}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "10px" }}>
          <h3 style={{ margin: 0, fontSize: "14px", fontWeight: 600 }}>Upcoming</h3>
          <button onClick={() => setTab("lessons")} style={styles.btnGhost}>View all →</button>
        </div>
        {data.lessons.filter(l => l.date >= today()).sort((a, b) => a.date.localeCompare(b.date)).slice(0, 5).length === 0
          ? <div style={{ color: T.textMuted, fontSize: "13px", padding: "8px 0" }}>No upcoming lessons</div>
          : data.lessons.filter(l => l.date >= today()).sort((a, b) => a.date.localeCompare(b.date)).slice(0, 5).map(l => {
            const names = (l.student_ids || []).map(id => data.students.find(s => s.id === id)?.name || "?").join(", ");
            return (
              <div key={l.id} style={{ padding: "8px 0", borderBottom: `1px solid ${T.border}` }}>
                <Row left={l.title || l.type} right={fmt(l.date)} bold />
                <div style={{ fontSize: "12px", color: T.textMuted, marginTop: "2px" }}>{names} · {l.time}</div>
              </div>
            );
          })
        }
      </div>
    </div>
  );
}

// ─── Admin: Students ───
function AdminStudents({ data, reload }) {
  const [showAdd, setShowAdd] = useState(false);
  const [editing, setEditing] = useState(null);
  const [search, setSearch] = useState("");
  const [form, setForm] = useState({ name: "", email: "", phone: "", notes: "", password: "" });
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");

  const filtered = data.students.filter(s => s.name?.toLowerCase().includes(search.toLowerCase()) || s.email?.toLowerCase().includes(search.toLowerCase()));

  const getCredits = (sid) => {
    const bought = data.purchases.filter(p => p.student_id === sid).reduce((a, p) => a + (p.sessions || 0), 0);
    const used = data.lessons.filter(l => l.student_ids?.includes(sid) && l.status !== "cancelled").length;
    return Math.max(0, bought - used);
  };

  const saveStudent = async () => {
    setBusy(true); setErr("");
    try {
      if (editing) {
        await api.patch(`/students/${editing.id}`, { name: form.name, email: form.email, phone: form.phone, notes: form.notes, password: form.password || undefined });
      } else {
        await api.post("/students", { name: form.name, email: form.email, phone: form.phone, notes: form.notes, password: form.password });
      }
      await reload();
      setShowAdd(false); setEditing(null); setForm({ name: "", email: "", phone: "", notes: "", password: "" });
    } catch (e) { setErr(e.message); }
    setBusy(false);
  };

  const openEdit = (s) => { setEditing(s); setForm({ name: s.name, email: s.email, phone: s.phone || "", notes: s.notes || "", password: "" }); setShowAdd(true); };

  return (
    <div style={{ animation: "fadeIn 0.2s ease" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "12px", gap: "8px", flexWrap: "wrap" }}>
        <h2 style={{ fontSize: "18px", fontWeight: 700, margin: 0 }}>Students</h2>
        <button onClick={() => { setEditing(null); setForm({ name: "", email: "", phone: "", notes: "", password: "" }); setShowAdd(true); }} style={styles.btnPrimary}><Icon d={Icons.plus} size={15} /> Add</button>
      </div>
      <div style={{ marginBottom: "12px" }}><Input placeholder="Search students…" value={search} onChange={e => setSearch(e.target.value)} /></div>

      {filtered.length === 0
        ? <EmptyState icon={Icons.users} message="No students yet." />
        : filtered.map(s => {
          const c = getCredits(s.id);
          return (
            <ListCard key={s.id} onClick={() => openEdit(s)}>
              <Row left={s.name} right={<span style={styles.badge(c > 0 ? T.accent : T.warn, c > 0 ? T.accentLight : T.warnLight)}>{c} credits</span>} bold />
              <div style={{ fontSize: "12px", color: T.textMuted, marginTop: "3px" }}>{s.email}</div>
            </ListCard>
          );
        })
      }

      <Modal open={showAdd} onClose={() => { setShowAdd(false); setEditing(null); }} title={editing ? "Edit Student" : "Add Student"}>
        <ErrBanner msg={err} />
        <Field label="Full Name"><Input value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} placeholder="Jane Smith" autoFocus /></Field>
        <Field label="Email (login)"><Input value={form.email} onChange={e => setForm({ ...form, email: e.target.value })} placeholder="jane@example.com" /></Field>
        <Field label="Phone"><Input value={form.phone} onChange={e => setForm({ ...form, phone: e.target.value })} placeholder="+971 …" /></Field>
        <Field label={editing ? "New Password (blank = keep)" : "Password"}><Input type="password" value={form.password} onChange={e => setForm({ ...form, password: e.target.value })} placeholder={editing ? "••••••••" : "welcome123"} /></Field>
        <Field label="Notes"><Input value={form.notes} onChange={e => setForm({ ...form, notes: e.target.value })} placeholder="Any notes…" /></Field>
        <div style={{ display: "flex", gap: "8px", justifyContent: "flex-end", marginTop: "8px" }}>
          <button onClick={() => { setShowAdd(false); setEditing(null); }} style={styles.btnSecondary}>Cancel</button>
          <button onClick={saveStudent} disabled={busy || !form.name || !form.email} style={{ ...styles.btnPrimary, opacity: (busy || !form.name || !form.email) ? 0.5 : 1 }}>{busy ? "Saving…" : editing ? "Update" : "Add"}</button>
        </div>
      </Modal>
    </div>
  );
}

// ─── Admin: Lessons ───
function AdminLessons({ data, reload }) {
  const [showAdd, setShowAdd] = useState(false);
  const [form, setForm] = useState({ title: "", type: "private", date: today(), time: "10:00", duration: 60, student_ids: [], notes: "", status: "scheduled" });
  const [editing, setEditing] = useState(null);
  const [filter, setFilter] = useState("upcoming");
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");

  const lessons = useMemo(() => {
    let ls = [...data.lessons];
    if (filter === "upcoming") ls = ls.filter(l => l.date >= today());
    else if (filter === "past") ls = ls.filter(l => l.date < today());
    return ls.sort((a, b) => filter === "past" ? b.date.localeCompare(a.date) : a.date.localeCompare(b.date));
  }, [data.lessons, filter]);

  const saveLesson = async () => {
    setBusy(true); setErr("");
    try {
      if (editing) {
        await api.patch(`/lessons/${editing.id}`, form);
      } else {
        await api.post("/lessons", form);
      }
      await reload();
      setShowAdd(false); setEditing(null);
      setForm({ title: "", type: "private", date: today(), time: "10:00", duration: 60, student_ids: [], notes: "", status: "scheduled" });
    } catch (e) { setErr(e.message); }
    setBusy(false);
  };

  const openEdit = (l) => {
    setEditing(l);
    setForm({ title: l.title || "", type: l.type, date: l.date, time: l.time || "10:00", duration: l.duration || 60, student_ids: l.student_ids || [], notes: l.notes || "", status: l.status || "scheduled" });
    setShowAdd(true);
  };

  const toggleStudent = (id) => setForm(f => ({ ...f, student_ids: f.student_ids.includes(id) ? f.student_ids.filter(x => x !== id) : [...f.student_ids, id] }));
  const statusColors = { scheduled: [T.accent, T.accentLight], completed: ["#6B7280", "#F3F4F6"], cancelled: [T.warn, T.warnLight] };

  return (
    <div style={{ animation: "fadeIn 0.2s ease" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "12px", gap: "8px", flexWrap: "wrap" }}>
        <h2 style={{ fontSize: "18px", fontWeight: 700, margin: 0 }}>Lessons</h2>
        <button onClick={() => { setEditing(null); setForm({ title: "", type: "private", date: today(), time: "10:00", duration: 60, student_ids: [], notes: "", status: "scheduled" }); setShowAdd(true); }} style={styles.btnPrimary}><Icon d={Icons.plus} size={15} /> Add</button>
      </div>
      <div style={{ display: "flex", gap: "4px", marginBottom: "12px" }}>
        {["upcoming", "past", "all"].map(f => (
          <button key={f} onClick={() => setFilter(f)} style={{ ...baseBtn, background: filter === f ? T.accentLight : "transparent", color: filter === f ? T.accent : T.textMuted, fontSize: "13px", textTransform: "capitalize", padding: "6px 12px" }}>{f}</button>
        ))}
      </div>

      {lessons.length === 0
        ? <EmptyState icon={Icons.calendar} message="No lessons found." />
        : lessons.map(l => {
          const names = (l.student_ids || []).map(id => data.students.find(s => s.id === id)?.name).filter(Boolean).join(", ") || "No students";
          const [sc, sbg] = statusColors[l.status] || statusColors.scheduled;
          return (
            <ListCard key={l.id} onClick={() => openEdit(l)}>
              <Row left={l.title || l.type} right={<span style={styles.badge(sc, sbg)}>{l.status}</span>} bold />
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: "12px", color: T.textMuted, marginTop: "3px", gap: "8px", flexWrap: "wrap" }}>
                <span>{names}</span>
                <span>{fmt(l.date)} · {l.time} · {l.duration}min</span>
              </div>
            </ListCard>
          );
        })
      }

      <Modal open={showAdd} onClose={() => { setShowAdd(false); setEditing(null); }} title={editing ? "Edit Lesson" : "Add Lesson"}>
        <ErrBanner msg={err} />
        <FormGrid>
          <Field label="Title"><Input value={form.title} onChange={e => setForm({ ...form, title: e.target.value })} placeholder="Voice coaching" autoFocus /></Field>
          <Field label="Type">
            <Select value={form.type} onChange={e => setForm({ ...form, type: e.target.value })}>
              <option value="private">Private</option><option value="group">Group</option>
            </Select>
          </Field>
          <Field label="Date"><Input type="date" value={form.date} onChange={e => setForm({ ...form, date: e.target.value })} /></Field>
          <Field label="Time"><Input type="time" value={form.time} onChange={e => setForm({ ...form, time: e.target.value })} /></Field>
          <Field label="Duration (min)"><Input type="number" value={form.duration} onChange={e => setForm({ ...form, duration: Number(e.target.value) })} /></Field>
          <Field label="Status">
            <Select value={form.status} onChange={e => setForm({ ...form, status: e.target.value })}>
              <option value="scheduled">Scheduled</option><option value="completed">Completed</option><option value="cancelled">Cancelled</option>
            </Select>
          </Field>
        </FormGrid>
        <Field label="Students">
          <div style={{ display: "flex", flexWrap: "wrap", gap: "6px" }}>
            {data.students.map(s => (
              <button key={s.id} onClick={() => toggleStudent(s.id)}
                style={{ ...baseBtn, fontSize: "12px", padding: "5px 10px", background: form.student_ids.includes(s.id) ? T.accent : T.surfaceAlt, color: form.student_ids.includes(s.id) ? "#fff" : T.text, border: `1px solid ${form.student_ids.includes(s.id) ? T.accent : T.border}` }}>
                {s.name}
              </button>
            ))}
            {data.students.length === 0 && <span style={{ fontSize: "13px", color: T.textMuted }}>Add students first</span>}
          </div>
        </Field>
        <Field label="Notes"><Input value={form.notes} onChange={e => setForm({ ...form, notes: e.target.value })} placeholder="Any notes…" /></Field>
        <div style={{ display: "flex", gap: "8px", justifyContent: "flex-end", marginTop: "8px" }}>
          <button onClick={() => { setShowAdd(false); setEditing(null); }} style={styles.btnSecondary}>Cancel</button>
          <button onClick={saveLesson} disabled={busy} style={{ ...styles.btnPrimary, opacity: busy ? 0.5 : 1 }}>{busy ? "Saving…" : editing ? "Update" : "Add Lesson"}</button>
        </div>
      </Modal>
    </div>
  );
}

// ─── Admin: Packages ───
function AdminPackages({ data, reload }) {
  const [showAdd, setShowAdd] = useState(false);
  const [editing, setEditing] = useState(null);
  const [form, setForm] = useState({ name: "", type: "single", lesson_type: "private", sessions: 1, price: 0 });
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");

  const savePackage = async () => {
    setBusy(true); setErr("");
    try {
      if (editing) {
        await api.patch(`/packages/${editing.id}`, { active: false });
        await api.post("/packages", { ...form, active: true });
      } else {
        await api.post("/packages", { ...form, active: true });
      }
      await reload();
      setShowAdd(false); setEditing(null); setForm({ name: "", type: "single", lesson_type: "private", sessions: 1, price: 0 });
    } catch (e) { setErr(e.message); }
    setBusy(false);
  };

  const toggleActive = async (pkg) => {
    try { await api.patch(`/packages/${pkg.id}`, { active: !pkg.active }); await reload(); }
    catch (e) { alert(e.message); }
  };

  const active = data.packages.filter(p => p.active);
  const inactive = data.packages.filter(p => !p.active);

  return (
    <div style={{ animation: "fadeIn 0.2s ease" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "4px", gap: "8px", flexWrap: "wrap" }}>
        <h2 style={{ fontSize: "18px", fontWeight: 700, margin: 0 }}>Packages</h2>
        <button onClick={() => { setEditing(null); setForm({ name: "", type: "single", lesson_type: "private", sessions: 1, price: 0 }); setShowAdd(true); }} style={styles.btnPrimary}><Icon d={Icons.plus} size={15} /> Add</button>
      </div>
      <p style={{ fontSize: "12px", color: T.textMuted, marginBottom: "14px" }}>Editing creates a new version. Previously purchased packages are preserved.</p>

      {[...active, ...inactive].map(p => (
        <ListCard key={p.id}>
          <Row left={p.name} right={<span style={styles.badge(p.active ? T.accent : T.textMuted, p.active ? T.accentLight : T.surfaceAlt)}>{p.active ? "Active" : "Retired"}</span>} bold />
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: "4px" }}>
            <div style={{ fontSize: "12px", color: T.textMuted }}>{p.type} · {p.lesson_type} · {p.sessions} sessions · {currency(p.price)}</div>
            <div style={{ display: "flex", gap: "4px" }}>
              <button onClick={() => { setEditing(p); setForm({ name: p.name, type: p.type, lesson_type: p.lesson_type, sessions: p.sessions, price: p.price }); setShowAdd(true); }} style={styles.btnGhost}><Icon d={Icons.edit} size={14} /></button>
              <button onClick={() => toggleActive(p)} style={styles.btnGhost}>{p.active ? "✕" : "↩"}</button>
            </div>
          </div>
        </ListCard>
      ))}

      <Modal open={showAdd} onClose={() => { setShowAdd(false); setEditing(null); }} title={editing ? "Edit Package (new version)" : "New Package"}>
        <ErrBanner msg={err} />
        <Field label="Package Name"><Input value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} placeholder="10 Private Lessons" autoFocus /></Field>
        <FormGrid>
          <Field label="Type">
            <Select value={form.type} onChange={e => setForm({ ...form, type: e.target.value })}>
              <option value="single">Single</option><option value="block">Block</option><option value="subscription">Subscription</option><option value="other">Other</option>
            </Select>
          </Field>
          <Field label="Lesson Type">
            <Select value={form.lesson_type} onChange={e => setForm({ ...form, lesson_type: e.target.value })}>
              <option value="private">Private</option><option value="group">Group</option><option value="any">Any</option>
            </Select>
          </Field>
          <Field label="Sessions"><Input type="number" min="1" value={form.sessions} onChange={e => setForm({ ...form, sessions: Number(e.target.value) })} /></Field>
          <Field label="Price (AED)"><Input type="number" min="0" value={form.price} onChange={e => setForm({ ...form, price: Number(e.target.value) })} /></Field>
        </FormGrid>
        <div style={{ display: "flex", gap: "8px", justifyContent: "flex-end", marginTop: "8px" }}>
          <button onClick={() => { setShowAdd(false); setEditing(null); }} style={styles.btnSecondary}>Cancel</button>
          <button onClick={savePackage} disabled={busy || !form.name} style={{ ...styles.btnPrimary, opacity: (busy || !form.name) ? 0.5 : 1 }}>{busy ? "Saving…" : editing ? "Save New Version" : "Create"}</button>
        </div>
      </Modal>
    </div>
  );
}

// ─── Admin: Payments ───
function AdminPayments({ data, reload }) {
  const [showAdd, setShowAdd] = useState(false);
  const [form, setForm] = useState({ student_id: "", package_id: "", paid: 0, method: "cash", discount: 0, notes: "", date: today() });
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const activePackages = data.packages.filter(p => p.active);

  const handlePkgChange = (pkgId) => {
    const pkg = data.packages.find(p => p.id === pkgId);
    setForm(f => ({ ...f, package_id: pkgId, paid: pkg ? pkg.price - f.discount : f.paid }));
  };

  const savePurchase = async () => {
    setBusy(true); setErr("");
    try {
      const pkg = data.packages.find(p => p.id === form.package_id);
      await api.post("/purchases", {
        student_id: form.student_id,
        package_id: form.package_id,
        package_name: pkg?.name || "Custom",
        sessions: pkg?.sessions || 0,
        paid: form.paid,
        discount: form.discount,
        method: form.method,
        notes: form.notes,
        date: form.date,
      });
      await reload();
      setShowAdd(false);
      setForm({ student_id: "", package_id: "", paid: 0, method: "cash", discount: 0, notes: "", date: today() });
    } catch (e) { setErr(e.message); }
    setBusy(false);
  };

  const all = [...data.purchases].sort((a, b) => (b.date || "").localeCompare(a.date || ""));

  return (
    <div style={{ animation: "fadeIn 0.2s ease" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "12px", gap: "8px", flexWrap: "wrap" }}>
        <h2 style={{ fontSize: "18px", fontWeight: 700, margin: 0 }}>Payments</h2>
        <button onClick={() => setShowAdd(true)} style={styles.btnPrimary}><Icon d={Icons.plus} size={15} /> Record</button>
      </div>

      {all.length === 0
        ? <EmptyState icon={Icons.dollar} message="No payments recorded yet." />
        : all.map(p => (
          <ListCard key={p.id}>
            <Row left={data.students.find(s => s.id === p.student_id)?.name || "Unknown"} right={<span style={{ fontWeight: 600, color: T.accent }}>{currency(p.paid)}</span>} bold />
            <div style={{ display: "flex", justifyContent: "space-between", fontSize: "12px", color: T.textMuted, marginTop: "3px", gap: "8px", flexWrap: "wrap" }}>
              <span>{p.package_name} · {p.sessions} sessions · {p.method}</span>
              <span>{fmt(p.date)}{p.discount > 0 ? ` · -${currency(p.discount)}` : ""}</span>
            </div>
          </ListCard>
        ))
      }

      <Modal open={showAdd} onClose={() => setShowAdd(false)} title="Record Payment">
        <ErrBanner msg={err} />
        <FormGrid>
          <Field label="Student">
            <Select value={form.student_id} onChange={e => setForm({ ...form, student_id: e.target.value })}>
              <option value="">Select…</option>
              {data.students.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
            </Select>
          </Field>
          <Field label="Package">
            <Select value={form.package_id} onChange={e => handlePkgChange(e.target.value)}>
              <option value="">Select…</option>
              {activePackages.map(p => <option key={p.id} value={p.id}>{p.name} — {currency(p.price)}</option>)}
            </Select>
          </Field>
          <Field label="Date"><Input type="date" value={form.date} onChange={e => setForm({ ...form, date: e.target.value })} /></Field>
          <Field label="Method">
            <Select value={form.method} onChange={e => setForm({ ...form, method: e.target.value })}>
              <option value="cash">Cash</option><option value="transfer">Transfer</option><option value="card">Card</option><option value="other">Other</option>
            </Select>
          </Field>
          <Field label="Discount (AED)"><Input type="number" min="0" value={form.discount} onChange={e => { const d = Number(e.target.value); const pkg = data.packages.find(p => p.id === form.package_id); setForm({ ...form, discount: d, paid: pkg ? pkg.price - d : form.paid }); }} /></Field>
          <Field label="Paid (AED)"><Input type="number" min="0" value={form.paid} onChange={e => setForm({ ...form, paid: Number(e.target.value) })} /></Field>
        </FormGrid>
        <Field label="Notes"><Input value={form.notes} onChange={e => setForm({ ...form, notes: e.target.value })} placeholder="Optional…" /></Field>
        <div style={{ display: "flex", gap: "8px", justifyContent: "flex-end", marginTop: "8px" }}>
          <button onClick={() => setShowAdd(false)} style={styles.btnSecondary}>Cancel</button>
          <button onClick={savePurchase} disabled={busy || !form.student_id || !form.package_id} style={{ ...styles.btnPrimary, opacity: (busy || !form.student_id || !form.package_id) ? 0.5 : 1 }}>{busy ? "Saving…" : "Record"}</button>
        </div>
      </Modal>
    </div>
  );
}

// ═══════════════════════════════════════════════
// CLIENT DASHBOARD
// ═══════════════════════════════════════════════
function ClientDashboard({ data, user, onLogout }) {
  const myPurchases = data.purchases.filter(p => p.student_id === user.id);
  const myLessons = data.lessons.filter(l => l.student_ids?.includes(user.id));
  const upcoming = myLessons.filter(l => l.date >= today() && l.status !== "cancelled").sort((a, b) => a.date.localeCompare(b.date));
  const past = myLessons.filter(l => l.date < today() || l.status === "completed").sort((a, b) => b.date.localeCompare(a.date));
  const totalSessions = myPurchases.reduce((a, p) => a + (p.sessions || 0), 0);
  const usedSessions = myLessons.filter(l => l.status !== "cancelled").length;
  const credits = Math.max(0, totalSessions - usedSessions);

  return (
    <div style={{ fontFamily: T.font, minHeight: "100vh", background: T.bg, color: T.text }}>
      <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
      <GlobalStyles />

      <header style={{ background: T.surface, borderBottom: `1px solid ${T.border}`, padding: "0 16px", display: "flex", alignItems: "center", justifyContent: "space-between", height: "52px" }}>
        <div style={{ display: "flex", alignItems: "center", gap: "8px", minWidth: 0 }}>
          <span style={{ fontSize: "17px", fontWeight: 700, letterSpacing: "-0.5px" }}>Lessons</span>
          <span style={{ fontSize: "13px", color: T.textMuted, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{user.name}</span>
        </div>
        <button onClick={onLogout} style={styles.btnGhost}><Icon d={Icons.logout} size={16} /></button>
      </header>

      <main style={{ maxWidth: "800px", margin: "0 auto", padding: "16px", animation: "fadeIn 0.2s ease" }}>
        <div className="stat-row" style={{ marginBottom: "16px" }}>
          <Stat label="Credits" value={credits} sub="remaining" color={credits > 0 ? T.accent : T.warn} />
          <Stat label="Purchased" value={totalSessions} sub="total" />
          <Stat label="Taken" value={usedSessions} sub="lessons" />
        </div>

        <div style={{ ...styles.card, marginBottom: "12px" }}>
          <h3 style={{ margin: "0 0 10px", fontSize: "14px", fontWeight: 600 }}>Upcoming Lessons</h3>
          {upcoming.length === 0
            ? <div style={{ color: T.textMuted, fontSize: "13px", padding: "6px 0" }}>No upcoming lessons scheduled.</div>
            : upcoming.map(l => (
              <div key={l.id} style={{ padding: "8px 0", borderBottom: `1px solid ${T.border}` }}>
                <Row left={l.title || l.type} right={<span style={styles.badge()}>{l.type}</span>} bold />
                <div style={{ fontSize: "12px", color: T.textMuted, marginTop: "2px" }}>{fmt(l.date)} · {l.time} · {l.duration}min</div>
              </div>
            ))
          }
        </div>

        <div style={{ ...styles.card, marginBottom: "12px" }}>
          <h3 style={{ margin: "0 0 10px", fontSize: "14px", fontWeight: 600 }}>Lesson History</h3>
          {past.length === 0
            ? <div style={{ color: T.textMuted, fontSize: "13px", padding: "6px 0" }}>No past lessons yet.</div>
            : past.slice(0, 10).map(l => (
              <div key={l.id} style={{ padding: "6px 0", borderBottom: `1px solid ${T.border}`, fontSize: "13px" }}>
                <Row left={l.title || l.type} right={fmt(l.date)} />
              </div>
            ))
          }
        </div>

        <div style={styles.card}>
          <h3 style={{ margin: "0 0 10px", fontSize: "14px", fontWeight: 600 }}>Payment History</h3>
          {myPurchases.length === 0
            ? <div style={{ color: T.textMuted, fontSize: "13px", padding: "6px 0" }}>No payments on record.</div>
            : myPurchases.sort((a, b) => (b.date || "").localeCompare(a.date || "")).map(p => (
              <div key={p.id} style={{ padding: "8px 0", borderBottom: `1px solid ${T.border}` }}>
                <Row left={p.package_name} right={<span style={{ fontWeight: 600, color: T.accent }}>{currency(p.paid)}</span>} bold />
                <div style={{ fontSize: "12px", color: T.textMuted, marginTop: "2px" }}>
                  {p.sessions} sessions · {fmt(p.date)}
                  {p.discount > 0 && <span> · <span style={{ color: T.warn }}>-{currency(p.discount)}</span></span>}
                </div>
              </div>
            ))
          }
        </div>
      </main>
    </div>
  );
}
