/* Ventas y pagos — búsqueda por alumno, calendario y comprobante PDF */

const StudentLookupModal = ({ open, onClose, theme, students, onSelect }) => {
  const [digits, setDigits] = React.useState('');
  const [search, setSearch] = React.useState('');
  const [err, setErr] = React.useState('');

  React.useEffect(() => {
    if (!open) return;
    setDigits('');
    setSearch('');
    setErr('');
  }, [open]);

  const list = (students || []).filter(s => !isDemoStudentCode(s.id));
  const q = search.trim().toLowerCase();

  const filtered = list.filter((a) => {
    if (!q) return true;
    const hay = [a.name, a.id, a.tutor, a.phone, a.email].join(' ').toLowerCase();
    return hay.includes(q);
  }).slice(0, 12);

  const pickByDigits = () => {
    const code = typeof buildTecStudentCode === 'function'
      ? buildTecStudentCode(digits)
      : (digits ? `TEC${String(digits).padStart(3, '0')}` : '');
    if (!code) { setErr('Escribe el número del ID (ej. 001).'); return; }
    const found = list.find(a => a.id === code);
    if (!found) { setErr(`No se encontró el alumno ${code}.`); return; }
    onSelect?.(found);
    onClose();
  };

  return (
    <Modal open={open} onClose={onClose} theme={theme} title="Buscar alumno" width={520}>
      <div style={{ padding: 24, display: 'grid', gap: 16 }}>
        <p style={{ margin: 0, fontSize: 13, color: theme.textDim, fontFamily: 'Inter, sans-serif' }}>
          Ingresa el ID o busca por nombre / tutor. Luego verás su calendario para registrar el pago del mes.
        </p>
        <div>
          <label style={{ fontSize: 11, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase' }}>ID del alumno</label>
          <div style={{ display: 'flex', marginTop: 8, gap: 0 }}>
            <span style={{
              padding: '12px 14px', background: theme.bgElev, border: `1px solid ${theme.border}`,
              borderRight: 'none', borderRadius: '8px 0 0 8px', fontWeight: 800, color: theme.primary,
              fontFamily: 'Bebas Neue, sans-serif', fontSize: 18, letterSpacing: 1,
            }}>TEC</span>
            <input
              value={digits}
              onChange={e => { setDigits(formatTecCodeDigitsInput(e.target.value)); setErr(''); }}
              onKeyDown={e => { if (e.key === 'Enter') pickByDigits(); }}
              placeholder="001"
              maxLength={3}
              style={{
                flex: 1, padding: '12px 14px', borderRadius: '0 8px 8px 0',
                border: `1px solid ${theme.border}`, background: theme.bgInput, color: theme.text,
                fontFamily: 'Bebas Neue, sans-serif', fontSize: 22, letterSpacing: 2,
              }}
            />
          </div>
          {digits && (
            <div style={{ fontSize: 11, color: theme.textDim, marginTop: 6, fontFamily: 'Inter, sans-serif' }}>
              Vista: <strong style={{ color: theme.primary }}>{buildTecStudentCode?.(digits) || `TEC${digits}`}</strong>
            </div>
          )}
        </div>
        <Btn theme={theme} icon="search" onClick={pickByDigits}>Continuar con este ID</Btn>

        <div style={{ borderTop: `1px solid ${theme.border}`, paddingTop: 12 }}>
          <Input theme={theme} placeholder="Buscar por nombre, tutor, teléfono…" icon="search"
            value={search} onChange={e => setSearch(e.target.value)} />
        </div>

        {q && (
          <div style={{ display: 'grid', gap: 8, maxHeight: 220, overflowY: 'auto' }}>
            {filtered.length === 0 ? (
              <p style={{ fontSize: 13, color: theme.textMute, margin: 0 }}>Sin coincidencias.</p>
            ) : filtered.map(a => (
              <button key={a._uuid} type="button" onClick={() => { onSelect?.(a); onClose(); }} style={{
                display: 'flex', alignItems: 'center', gap: 12, padding: 12, borderRadius: 10,
                border: `1px solid ${theme.border}`, background: theme.bgInput, cursor: 'pointer', textAlign: 'left',
              }}>
                {a.photoUrl ? (
                  <img src={a.photoUrl} alt="" style={{ width: 40, height: 40, borderRadius: '50%', objectFit: 'cover' }} />
                ) : (
                  <Avatar name={a.name} size={40} theme={theme} />
                )}
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 700, color: theme.text, fontSize: 13 }}>{a.name}</div>
                  <div style={{ fontSize: 11, color: theme.textMute }}>{a.id} · {a.tutor}</div>
                </div>
                <Icon name="arrowRight" size={14} color={theme.primary} />
              </button>
            ))}
          </div>
        )}

        {err && <div style={{ color: theme.danger, fontSize: 13 }}>{err}</div>}
      </div>
    </Modal>
  );
};

const PaymentReceiptDetailModal = ({ open, onClose, theme, alumno, paymentId, onReload }) => {
  const [row, setRow] = React.useState(null);
  const [loading, setLoading] = React.useState(false);
  const [pdfBusy, setPdfBusy] = React.useState(false);
  const [waBusy, setWaBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  React.useEffect(() => {
    if (!open || !paymentId) { setRow(null); return; }
    let cancelled = false;
    setLoading(true);
    setErr('');
    (async () => {
      try {
        const data = await fetchPaymentDetailAdmin(paymentId);
        if (!cancelled) setRow(data);
      } catch (e) {
        if (!cancelled) setErr(e.message);
      }
      if (!cancelled) setLoading(false);
    })();
    return () => { cancelled = true; };
  }, [open, paymentId]);

  const paidAt = row?.paid_at || row?.created_at;
  const registeredLabel = paidAt
    ? new Date(paidAt).toLocaleString('es-MX', {
      weekday: 'long', day: 'numeric', month: 'long', year: 'numeric',
      hour: '2-digit', minute: '2-digit', second: '2-digit',
    })
    : '—';

  const downloadPdf = async () => {
    if (!row || !alumno) return;
    setPdfBusy(true);
    try {
      const settings = await fetchAcademySettings();
      await exportPaymentReceiptPdf(alumno, row, settings, theme);
    } catch (e) { alert(e.message); }
    setPdfBusy(false);
  };

  const sendWaPdf = async () => {
    if (!row || !alumno) return;
    if (typeof sendPaymentReceiptPdfViaWhatsApp !== 'function') {
      alert('Módulo PDF no cargado. Recarga la página (F5).');
      return;
    }
    const hasPhone = (alumno.phone && alumno.phone !== '—')
      || (alumno.student_phone && alumno.student_phone !== '—');
    if (!hasPhone) {
      alert('Registra el teléfono del tutor o del alumno para enviar el comprobante por WhatsApp.');
      return;
    }
    setWaBusy(true);
    try {
      const settings = await fetchAcademySettings();
      const sent = await sendPaymentReceiptPdfViaWhatsApp(alumno, row, { settings, theme });
      const dest = sent?.chatId ? `\n\nChat WhatsApp: ${sent.chatId}` : '';
      alert(`Comprobante enviado por WhatsApp al teléfono registrado.${dest}\n\nSi no lo ves en el móvil, abre Chrome del bot y confirma que el mensaje salió en ese chat.`);
    } catch (e) {
      if (e?.name !== 'AbortError') alert(e?.message || 'No se pudo enviar el comprobante.');
    }
    setWaBusy(false);
  };

  const due = row?.due_date ? new Date(row.due_date) : null;
  const mesLabel = due && !Number.isNaN(due.getTime())
    ? due.toLocaleDateString('es-MX', { month: 'long', year: 'numeric' })
    : (row?.concept || '—');

  return (
    <Modal open={open} onClose={onClose} theme={theme} title="Comprobante de pago" width={480}>
      <div style={{ padding: 24, display: 'grid', gap: 14 }}>
        {loading ? <LoadingBlock theme={theme} label="Cargando…" /> : err ? (
          <div style={{ color: theme.danger, fontSize: 13 }}>{err}</div>
        ) : row ? (
          <>
            <div style={{
              padding: 14, borderRadius: 10, background: `${theme.success}18`,
              border: `1px solid ${theme.success}44`,
            }}>
              <div style={{ fontSize: 10, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase' }}>Fecha y hora del registro</div>
              <div style={{ fontSize: 15, color: theme.text, fontWeight: 700, marginTop: 6, fontFamily: 'Inter, sans-serif' }}>
                {registeredLabel}
              </div>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
              {[
                ['Alumno', alumno?.name || '—'],
                ['ID', alumno?.id || '—'],
                ['Periodo', mesLabel],
                ['Concepto', row.concept || 'Mensualidad'],
                ['Monto', `$${Number(row.amount || 0).toLocaleString('es-MX')} MXN`],
                ['Método', row.receipt_path ? 'Transferencia' : 'Registro admin'],
                ['Referencia', row.transfer_reference || '—'],
              ].map(([l, v]) => (
                <div key={l} style={{ padding: 10, borderRadius: 8, background: theme.bgInput, border: `1px solid ${theme.border}` }}>
                  <div style={{ fontSize: 10, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase' }}>{l}</div>
                  <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginTop: 4 }}>{v}</div>
                </div>
              ))}
            </div>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              <Btn theme={theme} icon="download" onClick={downloadPdf} disabled={pdfBusy || waBusy}>
                {pdfBusy ? 'Generando PDF…' : 'Descargar comprobante PDF'}
              </Btn>
              <Btn theme={theme} kind="wa" icon="wa" onClick={sendWaPdf} disabled={pdfBusy || waBusy}>
                {waBusy ? 'Enviando…' : 'Enviar comprobante por WhatsApp'}
              </Btn>
            </div>
          </>
        ) : null}
      </div>
      <div style={{ padding: '12px 24px', borderTop: `1px solid ${theme.border}`, display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
        <Btn theme={theme} kind="ghost" onClick={onClose} disabled={waBusy}>Cerrar</Btn>
      </div>
    </Modal>
  );
};

const RegisterMonthPaymentModal = ({ open, onClose, theme, alumno, monthSlot, calendarYear, onSaved }) => {
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const { data: settings } = useLiveData(
    () => (open ? fetchAcademySettings() : Promise.resolve(DEFAULT_ACADEMY_SETTINGS)),
    [open]
  );

  if (!monthSlot || !alumno) return null;

  const year = calendarYear || new Date().getFullYear();
  const mi = monthSlot.monthIndex ?? MONTH_KEYS.indexOf(monthSlot.key);
  const dueDate = settings && typeof dueDateForBillingMonth === 'function'
    ? dueDateForBillingMonth(settings, year, mi)
    : null;
  const isAdvance = !!monthSlot.advancePay
    || (typeof isFutureBillingMonth === 'function' && isFutureBillingMonth(year, mi));
  const baseCharge = settings && typeof baseBillingMonthCharge === 'function'
    ? baseBillingMonthCharge(settings)
    : { amt: Number(settings?.monthly_fee) || Number(monthSlot.amt) || 0, formula: '' };
  const base = baseCharge.amt;
  const fees = isAdvance
    ? { total: Number(monthSlot.amt) || base, formula: monthSlot.feeFormula || baseCharge.formula }
    : (settings && dueDate && typeof computeLateFees === 'function'
      ? computeLateFees(base, dueDate, settings)
      : { total: Number(monthSlot.amt) || base, formula: '' });

  const submitPayment = async () => {
    if (monthSlot.status === 'revision' || monthSlot.status === 'en_revision') {
      setErr('Este mes tiene comprobante en revisión. Apruébalo en Verificar comprobantes.');
      return;
    }
    const advanceNote = isAdvance ? ' (pago anticipado, tarifa base)' : '';
    if (!window.confirm(`¿Registrar pago de ${monthSlot.name} ${year} por $${fees.total.toLocaleString('es-MX')}${advanceNote} para ${alumno.name}?`)) return;
    setBusy(true);
    setErr('');
    try {
      await registerStudentMonthPayment(alumno._uuid, year, mi, {
        settings,
        amount: fees.total,
        advancePay: isAdvance,
        joinedAt: alumno.joined_at,
      });
      notifyPaymentsChanged();
      onSaved?.();
      onClose();
    } catch (e) { setErr(e.message); }
    setBusy(false);
  };

  return (
    <Modal open={open} onClose={onClose} theme={theme} title={`Registrar pago — ${monthSlot.name} ${year}`} width={440}>
      <div style={{ padding: 24, display: 'grid', gap: 12 }}>
        <p style={{ margin: 0, fontSize: 13, color: theme.textDim, fontFamily: 'Inter, sans-serif' }}>
          Se marcará como <strong style={{ color: theme.success }}>pagado</strong> y se actualizará en Alumnos y en el portal del alumno.
          {isAdvance && (
            <span> Pago anticipado: solo <strong>tarifa base</strong> (periodo días {settings?.billing_period_start_day || 1}–{settings?.billing_period_end_day || 5}), sin recargos.</span>
          )}
        </p>
        <div style={{ padding: 14, borderRadius: 10, background: theme.bgInput, border: `1px solid ${theme.border}` }}>
          <div style={{ fontSize: 11, color: theme.textMute }}>Total a registrar</div>
          <div style={{ fontFamily: 'Bebas Neue, sans-serif', fontSize: 32, color: theme.primary, letterSpacing: 1 }}>
            ${fees.total.toLocaleString('es-MX')}
          </div>
          {fees.formula && <div style={{ fontSize: 11, color: theme.textDim, marginTop: 6 }}>{fees.formula}</div>}
        </div>
        {err && <div style={{ color: theme.danger, fontSize: 13 }}>{err}</div>}
        <Btn theme={theme} icon="check" onClick={submitPayment} disabled={busy}>{busy ? 'Guardando…' : 'Confirmar pago'}</Btn>
      </div>
    </Modal>
  );
};

const VentasPagosStudentModal = ({ open, onClose, theme, alumno, onSaved }) => {
  const [receiptPaymentId, setReceiptPaymentId] = React.useState(null);
  const [receiptOrder, setReceiptOrder] = React.useState(null);
  const [registerMonth, setRegisterMonth] = React.useState(null);
  const [pdfBusy, setPdfBusy] = React.useState(false);
  const [ordersTick, setOrdersTick] = React.useState(0);
  const [calendarYear, setCalendarYear] = React.useState(() => new Date().getFullYear());
  const uuid = alumno?._uuid;
  const code = alumno?.id;
  const YearNav = PaymentCalendarYearNav;
  const yearBounds = typeof getPaymentCalendarYearBounds === 'function'
    ? getPaymentCalendarYearBounds(alumno?.joined_at)
    : { minYear: new Date().getFullYear() - 2, maxYear: new Date().getFullYear() + 8 };

  React.useEffect(() => {
    if (open && uuid) setCalendarYear(new Date().getFullYear());
  }, [open, uuid]);

  React.useEffect(() => {
    const on = () => setOrdersTick((t) => t + 1);
    window.addEventListener('tecos:orders-changed', on);
    window.addEventListener('tecos:comprobantes-changed', on);
    return () => {
      window.removeEventListener('tecos:orders-changed', on);
      window.removeEventListener('tecos:comprobantes-changed', on);
    };
  }, []);

  const { data: storeOrders, loading: loadingOrders } = useLiveData(
    () => (uuid && code && open
      ? (typeof fetchStudentOrdersByUuidActive === 'function'
        ? fetchStudentOrdersByUuidActive(uuid, code)
        : fetchStudentOrdersByUuid(uuid, code).then(rows => (rows || []).filter((o) => {
          const s = String(o.s || '').toLowerCase();
          return s === 'pendiente' || s === 'en_revision' || s === 'rechazado';
        })))
      : Promise.resolve([])),
    [uuid, code, open, ordersTick]
  );

  const { data: calendarMonths, loading: loadingCalendar, reload: reloadCalendar } = useLiveData(
    () => (uuid && open
      ? fetchStudentPaymentCalendar(uuid, calendarYear, alumno?.joined_at, { allowAdvancePay: true })
      : Promise.resolve([])),
    [uuid, open, alumno?.joined_at, calendarYear]
  );

  const { data: billingSettings } = useLiveData(() => fetchAcademySettings(), []);

  if (!alumno) return null;

  const handleMonthClick = (m) => {
    if (m.status === 'sin_registro') return;
    if (m.status === 'pagado' && m.paymentId) {
      setReceiptPaymentId(m.paymentId);
      return;
    }
    if (m.status === 'revision' || m.status === 'en_revision') {
      alert('Comprobante en revisión. Ve a Verificar comprobantes para aprobar o rechazar.');
      return;
    }
    if (m.hideAmount && !m.advancePay) {
      alert('Este mes aún no está en periodo de cobro en el portal del alumno. Como admin puedes cobrar meses futuros con tarifa base (días 1–5) cuando el calendario muestre el monto.');
      return;
    }
    setRegisterMonth(m);
  };

  const afterSave = () => {
    reloadCalendar();
    onSaved?.();
  };

  const downloadHistoryPdf = async () => {
    setPdfBusy(true);
    try {
      const settings = billingSettings || await fetchAcademySettings();
      await exportStudentPaymentHistoryPdf(alumno, {
        settings,
        year: calendarYear,
      }, theme);
    } catch (e) { alert(e.message); }
    setPdfBusy(false);
  };

  return (
    <>
      <Modal open={open} onClose={onClose} theme={theme} width={760}>
        <div style={{
          padding: 24, display: 'flex', gap: 20, alignItems: 'center',
          background: `linear-gradient(135deg, ${theme.primary}22, ${theme.bgElev})`,
          borderBottom: `1px solid ${theme.border}`,
        }}>
          {alumno.photoUrl ? (
            <img src={alumno.photoUrl} alt="" style={{ width: 72, height: 72, borderRadius: '50%', objectFit: 'cover' }} />
          ) : (
            <Avatar name={alumno.name} size={72} color={theme.primary} />
          )}
          <div style={{ flex: 1 }}>
            <Badge theme={theme} color="info">{alumno.cat}</Badge>
            <h3 style={{ fontFamily: 'Bebas Neue, sans-serif', fontSize: 28, letterSpacing: 1, color: theme.text, margin: '4px 0', fontWeight: 400 }}>{alumno.name}</h3>
            <div style={{ display: 'flex', gap: 12, color: theme.textDim, fontSize: 13, fontFamily: 'Inter, sans-serif', flexWrap: 'wrap' }}>
              <span style={{ color: theme.primary, fontWeight: 700 }}>{alumno.id}</span>
              <span>·</span>
              <span>{alumno.tutor}</span>
              <span>·</span>
              <StatusPill status={alumno.status} theme={theme} />
              <span>·</span>
              <span style={{ color: alumno.adeudo > 0 ? theme.danger : theme.success, fontWeight: 700 }}>
                {alumno.adeudo > 0 ? `Adeudo mes: $${alumno.adeudo}` : 'Al corriente'}
              </span>
            </div>
          </div>
          <button type="button" onClick={onClose} style={{
            width: 36, height: 36, borderRadius: 8, background: theme.bgInput,
            border: `1px solid ${theme.border}`, color: theme.text, cursor: 'pointer',
            display: 'grid', placeItems: 'center',
          }}><Icon name="x" size={16} /></button>
        </div>

        <div style={{ padding: 24 }}>
          {billingSettings && (
            <Card theme={theme} style={{ padding: 12, marginBottom: 16, fontSize: 11, color: theme.textDim, fontFamily: 'Inter, sans-serif' }}>
              <strong style={{ color: theme.text }}>Tarifa base:</strong> ${Number(billingSettings.monthly_fee).toLocaleString('es-MX')}
              {' · '}
              <strong style={{ color: theme.text }}>Periodo normal:</strong> días {billingSettings.billing_period_start_day}–{billingSettings.billing_period_end_day}
            </Card>
          )}
          {loadingCalendar ? <LoadingBlock theme={theme} label="Calendario…" /> : (
            <>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12, marginBottom: 8, flexWrap: 'wrap' }}>
                <h4 style={{ fontFamily: 'Bebas Neue, sans-serif', fontSize: 22, color: theme.text, letterSpacing: 1, margin: 0, fontWeight: 400 }}>
                  CALENDARIO DE PAGOS
                </h4>
                {YearNav && (
                  <YearNav
                    theme={theme}
                    year={calendarYear}
                    onPrev={() => setCalendarYear((y) => Math.max(yearBounds.minYear, y - 1))}
                    onNext={() => setCalendarYear((y) => Math.min(yearBounds.maxYear, y + 1))}
                    minYear={yearBounds.minYear}
                    maxYear={yearBounds.maxYear}
                  />
                )}
              </div>
              <p style={{ fontSize: 12, color: theme.textDim, margin: '0 0 12px', fontFamily: 'Inter, sans-serif' }}>
                Toca un mes <strong>pagado</strong> para ver fecha de registro y descargar PDF. Toca un mes <strong>pendiente</strong> (incluye adelantos) para registrar pago con <strong>tarifa base días 1–5</strong>, sin recargos.
              </p>
              <PaymentGrid theme={theme} months={calendarMonths || []} onPayClick={handleMonthClick} adminCalendar />
              <div style={{ display: 'flex', gap: 14, marginTop: 12, flexWrap: 'wrap', fontSize: 11, color: theme.textDim, fontFamily: 'Inter, sans-serif' }}>
                <LegendDot c={theme.success} l="Pagado (ver comprobante)" />
                <LegendDot c={theme.warning} l="Pendiente (registrar)" />
                <LegendDot c={theme.danger} l="Vencido" />
                <LegendDot c={theme.info} l="En revisión → Comprobantes" />
              </div>
            </>
          )}

          <div style={{ marginTop: 28, paddingTop: 20, borderTop: `1px solid ${theme.border}` }}>
            <h4 style={{ fontFamily: 'Bebas Neue, sans-serif', fontSize: 22, color: theme.text, letterSpacing: 1, margin: '0 0 8px', fontWeight: 400 }}>
              COMPRAS TIENDA
            </h4>
            <p style={{ fontSize: 12, color: theme.textDim, margin: '0 0 12px', fontFamily: 'Inter, sans-serif' }}>
              Solo compras <strong>pendientes o en revisión</strong>. Si ya confirmaste el comprobante, verás la orden en <strong>Historial → Tienda online</strong> y el ingreso en el dashboard.
            </p>
            {loadingOrders ? (
              <LoadingBlock theme={theme} label="Cargando compras…" />
            ) : !(storeOrders || []).length ? (
              <p style={{ margin: 0, fontSize: 13, color: theme.textDim, fontFamily: 'Inter, sans-serif' }}>Sin compras registradas.</p>
            ) : (
              <div style={{ display: 'grid', gap: 8, maxHeight: 200, overflowY: 'auto' }}>
                {(storeOrders || []).map((c) => (
                  <div key={c.id} style={{
                    display: 'flex', alignItems: 'center', gap: 12, padding: 10, borderRadius: 8,
                    background: theme.bgInput, border: `1px solid ${theme.border}`,
                  }}>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontWeight: 600, fontSize: 13, color: theme.text, fontFamily: 'Inter, sans-serif' }}>{c.p}</div>
                      <div style={{ fontSize: 11, color: theme.textDim, marginTop: 2 }}>{c.n} · {c.d}</div>
                    </div>
                    <div style={{ fontFamily: 'Bebas Neue, sans-serif', fontSize: 18, color: theme.text }}>${c.a}</div>
                    <StatusPill status={c.s} theme={theme} />
                    <Btn theme={theme} size="sm" kind="soft" icon="doc" onClick={() => setReceiptOrder(c)} title="Comprobante PDF y WhatsApp">
                      Comprobante
                    </Btn>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>

        <div style={{ padding: '16px 24px', borderTop: `1px solid ${theme.border}`, display: 'flex', gap: 8, justifyContent: 'flex-end', flexWrap: 'wrap' }}>
          <Btn theme={theme} kind="soft" icon="download" onClick={downloadHistoryPdf} disabled={pdfBusy || loadingCalendar}>
            {pdfBusy ? 'Generando PDF…' : 'Historial PDF'}
          </Btn>
          <Btn theme={theme} kind="ghost" onClick={onClose}>Cerrar</Btn>
        </div>
      </Modal>

      <PaymentReceiptDetailModal
        open={!!receiptPaymentId}
        onClose={() => setReceiptPaymentId(null)}
        theme={theme}
        alumno={alumno}
        paymentId={receiptPaymentId}
        onReload={afterSave}
      />
      <StoreOrderReceiptDetailModal
        open={!!receiptOrder}
        onClose={() => setReceiptOrder(null)}
        theme={theme}
        alumno={alumno}
        order={receiptOrder}
      />
      <RegisterMonthPaymentModal
        open={!!registerMonth}
        onClose={() => setRegisterMonth(null)}
        theme={theme}
        alumno={alumno}
        monthSlot={registerMonth}
        calendarYear={calendarYear}
        onSaved={afterSave}
      />
    </>
  );
};

const PaymentDetailModal = ({ open, onClose, theme, payment, onSaved, onWhatsApp }) => {
  const [previewUrl, setPreviewUrl] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [rejectNotes, setRejectNotes] = React.useState('');

  React.useEffect(() => {
    if (!open || !payment) { setPreviewUrl(null); setRejectNotes(''); setErr(''); return; }
    let cancelled = false;
    (async () => {
      if (!payment.receipt_path || !isSupabaseReady()) { setPreviewUrl(null); return; }
      const url = await getReceiptSignedUrl(payment.receipt_path);
      if (!cancelled) setPreviewUrl(url);
    })();
    return () => { cancelled = true; };
  }, [open, payment?._paymentId, payment?.receipt_path]);

  if (!payment) return null;

  const canConfirm = ['pendiente', 'revision', 'vencido', 'urgente', 'rechazado'].includes(payment.estado);
  const hasReceipt = !!payment.receipt_path;
  const inReview = payment.dbStatus === 'en_revision' && hasReceipt;

  const run = async (fn) => {
    setBusy(true); setErr('');
    try {
      await fn();
      notifyPaymentsChanged();
      onSaved?.();
      onClose();
    } catch (e) { setErr(e.message); }
    setBusy(false);
  };

  const confirmPay = () => run(async () => {
    if (inReview) await approvePaymentReceipt(payment._paymentId);
    else await markPaymentPaid(payment._paymentId);
  });

  const rejectPay = () => {
    if (!rejectNotes.trim()) { setErr('Escribe el motivo del rechazo.'); return; }
    run(() => rejectPaymentReceipt({ paymentId: payment._paymentId, adminNotes: rejectNotes.trim() }));
  };

  const deletePay = () => {
    if (!confirm(`¿Eliminar el pago «${payment.concepto}» de ${payment.fullName}?`)) return;
    run(() => deletePayment(payment._paymentId));
  };

  const estado = payment.estado;
  let billingKind = 'pendiente';
  if (estado === 'pagado') billingKind = 'al_corriente';
  else if (estado === 'revision') billingKind = 'revision';
  else if (estado === 'rechazado') billingKind = 'rechazado';
  else if (estado === 'urgente') billingKind = 'urgente';
  else if (estado === 'vencido') billingKind = 'vencido';

  const waRecipient = {
    name: payment.fullName,
    alumno: payment.fullName,
    tutor: payment.tutor,
    tel: payment.phone,
    phone: payment.phone,
    mes: payment.mes,
    monto: billingKind === 'al_corriente' ? null : payment.monto,
    lim: payment.lim,
    dias: payment.daysLate,
    daysLate: payment.daysLate,
    billingKind,
    billingStatus: billingKind,
    tipo: typeof waBillingKindLabel === 'function'
      ? waBillingKindLabel(billingKind)
      : (billingKind === 'urgente' || billingKind === 'vencido' ? 'Recordatorio urgente' : 'Recordatorio de pago'),
    urgent: billingKind === 'urgente' || billingKind === 'vencido',
  };

  return (
    <Modal open={open} onClose={onClose} theme={theme} title="Detalle de pago" width={560}>
      <div style={{ padding: 24, display: 'grid', gap: 14 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <Avatar name={payment.fullName} size={48} theme={theme} />
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 700, color: theme.text, fontFamily: 'Inter, sans-serif' }}>{payment.fullName}</div>
            <div style={{ fontSize: 12, color: theme.textMute }}>{payment.id} · {payment.concepto}</div>
          </div>
          <StatusPill status={payment.estado} theme={theme} />
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          {[
            ['Monto base', `$${(payment.montoBase ?? payment.monto).toLocaleString('es-MX')}`],
            ...(payment.surchargeLines?.length ? payment.surchargeLines.map(l => [l.label, `$${l.amount.toLocaleString('es-MX')}`]) : []),
            ...(payment.recargo > 0 && !payment.surchargeLines?.length ? [['Recargo', `$${payment.recargo.toLocaleString('es-MX')}`]] : []),
            ['Tramo hoy', payment.tierLabel || '—'],
            ['Total a cobrar', `$${payment.monto.toLocaleString('es-MX')}`],
            ...(payment.feeFormula ? [['Cálculo', payment.feeFormula]] : []),
            ['Mes', payment.mes],
            ['Fecha límite', payment.lim],
            ['Fecha pago', payment.pago],
            ['Método', payment.metodo],
            ['Referencia', payment.transfer_reference || '—'],
          ].map(([l, v]) => (
            <div key={l} style={{ padding: 10, borderRadius: 8, background: theme.bgInput, border: `1px solid ${theme.border}` }}>
              <div style={{ fontSize: 10, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase' }}>{l}</div>
              <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginTop: 4 }}>{v}</div>
            </div>
          ))}
        </div>
        {payment.admin_notes && (
          <div style={{ padding: 12, borderRadius: 8, background: `${theme.warning}18`, border: `1px solid ${theme.warning}44`, fontSize: 13, color: theme.text }}>
            <strong>Notas admin:</strong> {payment.admin_notes}
          </div>
        )}
        {hasReceipt && (
          <div style={{ borderRadius: 10, overflow: 'hidden', border: `1px solid ${theme.border}`, background: theme.bgInput }}>
            {previewUrl ? (
              payment.receipt_path?.toLowerCase().endsWith('.pdf')
                ? <a href={previewUrl} target="_blank" rel="noopener noreferrer" style={{ display: 'block', padding: 20, textAlign: 'center', color: theme.primary }}>Abrir comprobante PDF</a>
                : <img src={previewUrl} alt="Comprobante" style={{ width: '100%', maxHeight: 280, objectFit: 'contain' }} />
            ) : (
              <div style={{ padding: 24, textAlign: 'center', color: theme.textMute, fontSize: 13 }}>Cargando comprobante…</div>
            )}
          </div>
        )}
        {inReview && (
          <Input theme={theme} label="Motivo de rechazo (si aplica)" value={rejectNotes}
            onChange={e => setRejectNotes(e.target.value)} placeholder="Ej. monto incorrecto, comprobante ilegible" />
        )}
        {err && <div style={{ color: theme.danger, fontSize: 13 }}>{err}</div>}
      </div>
      <div style={{ padding: '16px 24px', borderTop: `1px solid ${theme.border}`, display: 'flex', flexWrap: 'wrap', gap: 8, justifyContent: 'flex-end' }}>
        <Btn theme={theme} kind="ghost" onClick={onClose}>Cerrar</Btn>
        <Btn theme={theme} kind="ghost" icon="trash" onClick={deletePay} disabled={busy}>Eliminar</Btn>
        {payment.phone && payment.phone !== '—' && (
          <Btn theme={theme} kind="wa" icon="wa" onClick={() => onWhatsApp?.(waRecipient)} disabled={busy}>WhatsApp</Btn>
        )}
        {inReview && (
          <Btn theme={theme} kind="ghost" icon="x" onClick={rejectPay} disabled={busy}>Rechazar</Btn>
        )}
        {canConfirm && (
          <Btn theme={theme} icon="check" onClick={confirmPay} disabled={busy}>
            {busy ? 'Guardando…' : (inReview ? 'Aprobar comprobante' : 'Marcar pagado')}
          </Btn>
        )}
      </div>
    </Modal>
  );
};

/** Modal: comprobante PDF / WhatsApp de una compra en tienda (modal alumno / ventas). */
const StoreOrderReceiptDetailModal = ({ open, onClose, theme, alumno, order }) => {
  const [pdfBusy, setPdfBusy] = React.useState(false);
  const [waBusy, setWaBusy] = React.useState(false);

  React.useEffect(() => {
    if (!open) {
      setPdfBusy(false);
      setWaBusy(false);
    }
  }, [open]);

  if (!order || !alumno) return null;

  const portalOrder = typeof orderRowToPortalOrder === 'function' ? orderRowToPortalOrder(order) : order;
  const hasPhone = (alumno.phone && alumno.phone !== '—')
    || (alumno.student_phone && alumno.student_phone !== '—')
    || (portalOrder?.phone && portalOrder.phone !== '—');

  const downloadPdf = async () => {
    if (typeof exportStoreOrderReceiptPdf !== 'function') {
      alert('Módulo PDF no cargado. Recarga la página (F5).');
      return;
    }
    setPdfBusy(true);
    try {
      const settings = await fetchAcademySettings();
      await exportStoreOrderReceiptPdf(alumno, portalOrder, settings, theme);
    } catch (e) { alert(e?.message || 'No se pudo generar el PDF.'); }
    setPdfBusy(false);
  };

  const sendWaPdf = async () => {
    if (typeof sendStoreOrderReceiptPdfViaWhatsApp !== 'function') {
      alert('Módulo PDF no cargado. Recarga la página (F5).');
      return;
    }
    if (!hasPhone) {
      alert('Registra el teléfono del tutor o del alumno para enviar el comprobante por WhatsApp.');
      return;
    }
    setWaBusy(true);
    try {
      const settings = await fetchAcademySettings();
      const sent = await sendStoreOrderReceiptPdfViaWhatsApp(alumno, portalOrder, { settings, theme });
      const dest = sent?.chatId ? `\n\nChat WhatsApp: ${sent.chatId}` : '';
      alert(`Comprobante enviado por WhatsApp al teléfono registrado.${dest}\n\nSi no lo ves en el móvil, abre Chrome del bot y confirma que el mensaje salió en ese chat.`);
    } catch (e) {
      if (e?.name !== 'AbortError') alert(e?.message || 'No se pudo enviar el comprobante.');
    }
    setWaBusy(false);
  };

  const busy = pdfBusy || waBusy;

  return (
    <Modal open={open} onClose={onClose} theme={theme} title="Comprobante de compra" width={480}>
      <div style={{ padding: 24, display: 'grid', gap: 14 }}>
        <div style={{
          padding: 14, borderRadius: 10, background: `${theme.success}18`,
          border: `1px solid ${theme.success}44`,
        }}>
          <div style={{ fontSize: 10, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase' }}>Orden tienda</div>
          <div style={{ fontSize: 15, color: theme.text, fontWeight: 700, marginTop: 6, fontFamily: 'Inter, sans-serif' }}>
            {portalOrder.n || portalOrder.order_number || '—'}
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          {[
            ['Alumno', alumno?.name || '—'],
            ['ID', alumno?.id || '—'],
            ['Producto', portalOrder.p || '—'],
            ['Fecha', portalOrder.d || '—'],
            ['Monto', `$${Number(portalOrder.a || 0).toLocaleString('es-MX')} MXN`],
            ['Estado', portalOrder.s || '—'],
          ].map(([l, v]) => (
            <div key={l} style={{ padding: 10, borderRadius: 8, background: theme.bgInput, border: `1px solid ${theme.border}` }}>
              <div style={{ fontSize: 10, color: theme.textMute, fontWeight: 700, textTransform: 'uppercase' }}>{l}</div>
              <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginTop: 4 }}>{v}</div>
            </div>
          ))}
        </div>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          <Btn theme={theme} icon="download" onClick={downloadPdf} disabled={busy}>
            {pdfBusy ? 'Generando PDF…' : 'Descargar comprobante PDF'}
          </Btn>
          <Btn theme={theme} kind="wa" icon="wa" onClick={sendWaPdf} disabled={busy}>
            {waBusy ? 'Enviando…' : 'Enviar comprobante por WhatsApp'}
          </Btn>
        </div>
      </div>
      <div style={{ padding: '12px 24px', borderTop: `1px solid ${theme.border}`, display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
        <Btn theme={theme} kind="ghost" onClick={onClose} disabled={busy}>Cerrar</Btn>
      </div>
    </Modal>
  );
};

Object.assign(window, {
  StudentLookupModal,
  VentasPagosStudentModal,
  PaymentReceiptDetailModal,
  StoreOrderReceiptDetailModal,
  RegisterMonthPaymentModal,
  PaymentDetailModal,
});
