import type { FC } from 'react';
import { useEffect, useState, useCallback, useMemo } from 'react';
import { Link } from 'react-router-dom';
import {
  Search, Plus, Minus, X, Store, AlertTriangle, ShoppingBag, Star, Printer, Wallet, Trash2, Package,
} from 'lucide-react';
import Layout from '../components/Layout';
import {
  Card,
  Button,
  Input,
  Select,
  Modal,
  EmptyState,
  Skeleton,
  toast,
} from '../components/ui';
import { odooApi, type Service, type Patient, type InventoryItem, type PosCheckoutResult } from '../services/odoo';

const fmtMoney = (n: number) =>
  (n || 0).toLocaleString('es-MX', { style: 'currency', currency: 'MXN', maximumFractionDigits: 2 });

const fmtUsd = (n: number) =>
  `$${(n || 0).toLocaleString('es-MX', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} USD`;

const METODO_OPTIONS = [
  { value: 'cash', label: 'Efectivo' },
  { value: 'card', label: 'Tarjeta' },
  { value: 'transfer', label: 'Transferencia' },
  { value: 'stripe', label: 'Stripe' },
  { value: 'mercadopago', label: 'MercadoPago' },
];
const metodoLabel = (m: string) => METODO_OPTIONS.find((o) => o.value === m)?.label || m;

interface TicketLine {
  key: string;
  name: string;
  qty: number;
  price: number;
  service_id?: number;
  item_id?: number;
  stock?: number;
  unit?: string;
}

const Pos: FC = () => {
  // Catálogo
  const [catMode, setCatMode] = useState<'servicios' | 'articulos'>('servicios');
  const [services, setServices] = useState<Service[]>([]);
  const [catalogLoading, setCatalogLoading] = useState(true);
  const [search, setSearch] = useState('');
  const [categoria, setCategoria] = useState('');
  const [soloFavoritos, setSoloFavoritos] = useState(false);
  const [invItems, setInvItems] = useState<InventoryItem[]>([]);

  // Ticket
  const [lines, setLines] = useState<TicketLine[]>([]);
  const [discount, setDiscount] = useState('');
  const [paciente, setPaciente] = useState<Patient | null>(null);
  const [pacienteQuery, setPacienteQuery] = useState('');
  const [pacienteResults, setPacienteResults] = useState<Patient[]>([]);
  const [altaRapida, setAltaRapida] = useState(false);
  const [altaForm, setAltaForm] = useState({ name: '', phone: '' });

  // Cobro
  const [cobroOpen, setCobroOpen] = useState(false);
  const [metodo, setMetodo] = useState('cash');
  const [moneda, setMoneda] = useState<'MXN' | 'USD'>('MXN');
  const [recibido, setRecibido] = useState('');
  const [conPuntos, setConPuntos] = useState(false);
  const [cobrando, setCobrando] = useState(false);
  const [tcRate, setTcRate] = useState<number | null>(null);

  // Resultado
  const [resultado, setResultado] = useState<PosCheckoutResult | null>(null);

  // Corte de caja
  const [cajaAbierta, setCajaAbierta] = useState(true);

  // Mobile
  const [ticketMovil, setTicketMovil] = useState(false);

  // ---- Catálogo ----
  const loadServices = useCallback(async () => {
    try {
      setCatalogLoading(true);
      const res = await odooApi.getServices({ search: search || undefined, category: categoria || undefined, page_size: 200 });
      if (res.status === 'success') setServices(res.services);
    } catch (err) {
      toast.error('Error al cargar servicios');
      console.error(err);
    } finally {
      setCatalogLoading(false);
    }
  }, [search, categoria]);

  const loadItems = useCallback(async () => {
    try {
      setCatalogLoading(true);
      const res = await odooApi.getInventarioItems(search || undefined);
      if (res.status === 'success') setInvItems(res.items);
    } catch (err) {
      toast.error('Error al cargar artículos');
      console.error(err);
    } finally {
      setCatalogLoading(false);
    }
  }, [search]);

  useEffect(() => {
    const t = setTimeout(() => {
      if (catMode === 'servicios') loadServices();
      else loadItems();
    }, 300);
    return () => clearTimeout(t);
  }, [loadServices, loadItems, catMode]);

  useEffect(() => {
    odooApi.getCashClosings(new Date().toISOString().split('T')[0])
      .then((res) => {
        if (res.status === 'success') setCajaAbierta(res.cash_closings.some((c) => c.state === 'open'));
      })
      .catch(() => {});
  }, []);

  // Tipo de cambio USD/MXN: al montar y refresco cada 5 min
  useEffect(() => {
    const fetchTc = () => {
      odooApi.getExchangeRate()
        .then((res) => { if (res.current) setTcRate(res.current.rate); })
        .catch(() => {});
    };
    fetchTc();
    const interval = setInterval(fetchTc, 5 * 60 * 1000);
    return () => clearInterval(interval);
  }, []);

  // Búsqueda server-side de paciente
  useEffect(() => {
    if (paciente || altaRapida) return;
    if (pacienteQuery.trim().length < 2) {
      setPacienteResults([]);
      return;
    }
    const t = setTimeout(() => {
      odooApi.getPatients({ search: pacienteQuery.trim(), page_size: 8 })
        .then((res) => { if (res.status === 'success') setPacienteResults(res.patients); })
        .catch(() => {});
    }, 300);
    return () => clearTimeout(t);
  }, [pacienteQuery, paciente, altaRapida]);

  const categorias = useMemo(() => {
    const set = new Map<string, string>();
    services.forEach((s) => { if (s.category) set.set(s.category, s.category); });
    return [...set.keys()];
  }, [services]);

  const visibles = useMemo(
    () => (soloFavoritos ? services.filter((s) => s.is_favorite) : services),
    [services, soloFavoritos]
  );

  // Los artículos ya vienen filtrados del server-side (search)
  const visiblesItems = invItems;

  // ---- Ticket ----
  const addLine = (service: Service) => {
    setLines((prev) => {
      const key = `s-${service.id}`;
      const found = prev.find((l) => l.key === key);
      if (found) return prev.map((l) => (l.key === key ? { ...l, qty: l.qty + 1 } : l));
      return [...prev, { key, name: service.name, qty: 1, price: service.price, service_id: service.id }];
    });
  };

  const addItemLine = (item: InventoryItem) => {
    setLines((prev) => {
      const key = `i-${item.id}`;
      const found = prev.find((l) => l.key === key);
      if (found) return prev.map((l) => (l.key === key ? { ...l, qty: l.qty + 1 } : l));
      return [...prev, { key, name: item.name, qty: 1, price: item.price || 0, item_id: item.id, stock: item.qty, unit: item.unit }];
    });
  };

  const updateLine = (key: string, patch: Partial<TicketLine>) => {
    setLines((prev) => prev.map((l) => (l.key === key ? { ...l, ...patch } : l)));
  };

  const removeLine = (key: string) => setLines((prev) => prev.filter((l) => l.key !== key));

  const limpiarTicket = () => {
    if (lines.length === 0) return;
    if (window.confirm('¿Vaciar el ticket?')) setLines([]);
  };

  const subtotal = lines.reduce((a, l) => a + l.qty * l.price, 0);
  const discountNum = Math.min(parseFloat(discount) || 0, subtotal);
  const total = Math.max(0, subtotal - discountNum);
  const numItems = lines.reduce((a, l) => a + l.qty, 0);
  const puntosPaciente = paciente?.wallet_points ?? 0;
  const puedePuntos = puntosPaciente >= total && total > 0;
  // Equivalentes USD (si hay tipo de cambio configurado)
  const toUsd = (mxn: number): number | null => (tcRate ? mxn / tcRate : null);
  const recibidoMxn = recibido
    ? moneda === 'USD' && tcRate
      ? (parseFloat(recibido) || 0) * tcRate
      : parseFloat(recibido) || 0
    : 0;
  const cambio = metodo === 'cash' && recibido ? Math.max(0, recibidoMxn - total) : 0;
  const cambioUsd = moneda === 'USD' && tcRate ? cambio / tcRate : 0;

  const crearPacienteRapido = async () => {
    if (!altaForm.name.trim() || !altaForm.phone.trim()) {
      toast.error('Nombre y teléfono son obligatorios');
      return;
    }
    try {
      const res = await odooApi.createPatient({ name: altaForm.name.trim(), phone: altaForm.phone.trim() });
      if (res.status === 'success') {
        setPaciente(res.patient);
        setAltaRapida(false);
        setAltaForm({ name: '', phone: '' });
        toast.success('Paciente creado');
      }
    } catch (err) {
      toast.error('Error al crear paciente');
      console.error(err);
    }
  };

  const abrirCobro = () => {
    if (!paciente) {
      toast.error('Selecciona un paciente');
      return;
    }
    if (lines.length === 0) {
      toast.error('El ticket está vacío');
      return;
    }
    setMetodo('cash');
    setMoneda('MXN');
    setRecibido('');
    setConPuntos(false);
    setCobroOpen(true);
  };

  const cobrar = async () => {
    if (!paciente) return;
    try {
      setCobrando(true);
      const res = await odooApi.posCheckout({
        partner_id: paciente.id,
        lines: lines.map((l) => ({
          ...(l.service_id ? { service_id: l.service_id } : {}),
          ...(l.item_id ? { item_id: l.item_id } : {}),
          quantity: l.qty,
          price_unit: l.price,
        })),
        discount: discountNum,
        payment_method: metodo,
        amount_received: metodo === 'cash' && recibido ? parseFloat(recibido) : undefined,
        pay_with_points: conPuntos,
        currency: moneda,
      });
      if (res.status === 'success') {
        setResultado(res);
        setCobroOpen(false);
        toast.success(`Venta ${res.sale.name} cobrada`);
        if (res.stock_warnings && res.stock_warnings.length > 0) {
          res.stock_warnings.forEach((w) => toast.error(`Stock: ${w}`));
        }
      }
    } catch (err) {
      const msg = (err as { response?: { data?: { message?: string } } })?.response?.data?.message;
      toast.error(msg || 'Error al cobrar');
      console.error(err);
    } finally {
      setCobrando(false);
    }
  };

  const nuevaVenta = () => {
    setResultado(null);
    setLines([]);
    setDiscount('');
    setPaciente(null);
    setPacienteQuery('');
  };

  // ---- Bloques del ticket (desktop sticky y modal móvil) ----
  const pacienteBlock = paciente ? (
    <div className="flex items-center justify-between p-2.5 bg-theme-bg rounded-xl">
      <div className="min-w-0">
        <p className="text-sm font-medium text-theme-heading truncate">{paciente.name}</p>
        <p className="text-xs text-theme-muted flex items-center gap-1.5">
          {paciente.phone}
          {puntosPaciente > 0 && (
            <span className="inline-flex items-center gap-0.5"><Wallet size={11} /> {puntosPaciente} pts</span>
          )}
        </p>
      </div>
      <Button variant="ghost" size="sm" onClick={() => { setPaciente(null); setPacienteQuery(''); }}>Cambiar</Button>
    </div>
  ) : altaRapida ? (
    <div className="p-2.5 bg-theme-bg rounded-xl space-y-2">
      <Input placeholder="Nombre *" value={altaForm.name} onChange={(e) => setAltaForm({ ...altaForm, name: e.target.value })} />
      <Input placeholder="Teléfono *" value={altaForm.phone} onChange={(e) => setAltaForm({ ...altaForm, phone: e.target.value })} />
      <div className="flex gap-2">
        <Button variant="outline" size="sm" onClick={() => setAltaRapida(false)}>Cancelar</Button>
        <Button size="sm" onClick={crearPacienteRapido}>Crear paciente</Button>
      </div>
    </div>
  ) : (
    <div className="relative">
      <Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-theme-muted" />
      <Input
        placeholder="Buscar paciente por nombre o teléfono..."
        value={pacienteQuery}
        onChange={(e) => setPacienteQuery(e.target.value)}
        className="pl-10"
      />
      {pacienteResults.length > 0 && (
        <div className="absolute z-20 top-full left-0 right-0 mt-1 rounded-xl border border-theme-border bg-theme-surface shadow-card max-h-56 overflow-y-auto">
          {pacienteResults.map((p) => (
            <button
              key={p.id}
              type="button"
              onClick={() => { setPaciente(p); setPacienteResults([]); }}
              className="w-full text-left px-3 py-2 text-sm hover:bg-theme-bg transition"
            >
              <span className="font-medium text-theme-heading">{p.name}</span>
              <span className="text-theme-muted"> · {p.phone}</span>
            </button>
          ))}
          <button
            type="button"
            onClick={() => { setAltaRapida(true); setPacienteResults([]); }}
            className="w-full text-left px-3 py-2 text-sm text-theme-heading hover:bg-theme-bg border-t border-theme-border flex items-center gap-1.5"
          >
            <Plus size={14} /> Alta rápida de paciente
          </button>
        </div>
      )}
      {pacienteQuery.trim().length >= 2 && pacienteResults.length === 0 && (
        <button
          type="button"
          onClick={() => setAltaRapida(true)}
          className="mt-1.5 text-xs text-theme-heading underline flex items-center gap-1"
        >
          <Plus size={12} /> Alta rápida de paciente
        </button>
      )}
    </div>
  );

  const linesBlock = lines.length === 0 ? (
    <p className="text-sm text-theme-muted text-center py-8">Toca un servicio para agregarlo al ticket.</p>
  ) : (
    <div className="divide-y divide-theme-border">
      {lines.map((l) => (
        <div key={l.key} className="flex items-center gap-1.5 py-2">
          <button
            type="button"
            onClick={() => removeLine(l.key)}
            className="text-theme-muted hover:text-rose-600 shrink-0"
            title="Quitar"
          >
            <X size={14} />
          </button>
          <p className="flex-1 min-w-0 text-sm font-medium text-theme-heading truncate" title={l.name}>
            {l.item_id && <Package size={12} className="inline mr-1 text-theme-muted" />}
            {l.name}
            {l.item_id && l.stock !== undefined && (
              <span className="block text-[10px] font-normal text-theme-muted">{l.stock} {l.unit || 'pzas'} en existencia</span>
            )}
          </p>
          <div className="flex items-center gap-0.5 shrink-0">
            <Button variant="outline" size="sm" className="!px-1.5" onClick={() => updateLine(l.key, { qty: Math.max(1, l.qty - 1) })}><Minus size={12} /></Button>
            <span className="w-6 text-center text-sm font-medium text-theme-heading">{l.qty}</span>
            <Button variant="outline" size="sm" className="!px-1.5" onClick={() => updateLine(l.key, { qty: l.qty + 1 })}><Plus size={12} /></Button>
          </div>
          <input
            type="number"
            min={0}
            step={50}
            value={l.price}
            onChange={(e) => updateLine(l.key, { price: parseFloat(e.target.value) || 0 })}
            className="w-[70px] shrink-0 border border-theme-border-strong rounded-lg px-1.5 py-1 text-xs text-right"
            title="Precio unitario"
          />
          <span className="w-[72px] shrink-0 text-sm font-semibold text-theme-heading text-right">{fmtMoney(l.qty * l.price)}</span>
        </div>
      ))}
    </div>
  );

  const totalsBlock = (
    <>
      <div className="flex items-center justify-between text-sm">
        <span className="text-theme-muted">Subtotal</span>
        <span className="text-theme-heading">
          {fmtMoney(subtotal)}
          <span className="text-xs text-theme-muted ml-1.5" title={toUsd(subtotal) === null ? 'Configura el tipo de cambio en Configuración' : undefined}>
            {toUsd(subtotal) !== null ? `≈ ${fmtUsd(toUsd(subtotal)!)}` : '—'}
          </span>
        </span>
      </div>
      <div className="flex items-center justify-between text-sm gap-2">
        <span className="text-theme-muted">Descuento</span>
        <span className="flex items-center gap-1.5">
          {discountNum > 0 && toUsd(discountNum) !== null && (
            <span className="text-xs text-theme-muted">≈ {fmtUsd(toUsd(discountNum)!)}</span>
          )}
          <input
            type="number"
            min={0}
            step={50}
            value={discount}
            onChange={(e) => setDiscount(e.target.value)}
            placeholder="0"
            className="w-28 border border-theme-border-strong rounded-lg px-2 py-1 text-sm text-right"
          />
        </span>
      </div>
      <div className="flex items-center justify-between">
        <span className="text-base font-semibold text-theme-heading">Total</span>
        <span className="text-right">
          <span className="text-xl font-heading font-bold text-theme-heading">{fmtMoney(total)}</span>
          <span
            className="block text-xs text-theme-muted"
            title={toUsd(total) === null ? 'Configura el tipo de cambio en Configuración' : undefined}
          >
            {toUsd(total) !== null ? `≈ ${fmtUsd(toUsd(total)!)}` : '—'}
          </span>
        </span>
      </div>
      <Button
        className="w-full mt-1 !py-3 text-base"
        onClick={abrirCobro}
        disabled={lines.length === 0 || !paciente}
      >
        <ShoppingBag size={18} className="mr-2" />
        Cobrar {fmtMoney(total)}
      </Button>
    </>
  );

  return (
    <Layout title="Punto de Venta" subtitle="Arma el ticket y cobra en un solo paso">
      {!cajaAbierta && (
        <div className="mb-3">
          <span className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-theme-warning text-theme-warning-text text-xs">
            <AlertTriangle size={13} className="shrink-0" />
            Sin corte de caja abierto hoy
            <Link to="/cortes" className="font-semibold underline">Abrir caja</Link>
          </span>
        </div>
      )}

      <div className="flex flex-col lg:flex-row gap-4 items-start">
        {/* Catálogo */}
        <Card className="flex-1 min-w-0 w-full">
          <Card.Body>
            <div className="relative mb-3">
              <Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-theme-muted" />
              <Input
                placeholder={catMode === 'servicios' ? 'Buscar servicio...' : 'Buscar artículo...'}
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                className="pl-10"
              />
            </div>
            {/* Toggle Servicios / Artículos */}
            <div className="inline-flex rounded-full border border-theme-border-strong overflow-hidden mb-3">
              <button
                type="button"
                onClick={() => setCatMode('servicios')}
                className={`px-4 py-1.5 text-sm font-medium transition flex items-center gap-1.5 ${
                  catMode === 'servicios' ? 'bg-theme-accent text-theme-inverse' : 'bg-theme-surface text-theme-muted hover:bg-theme-bg'
                }`}
              >
                <Store size={14} /> Servicios
              </button>
              <button
                type="button"
                onClick={() => setCatMode('articulos')}
                className={`px-4 py-1.5 text-sm font-medium transition flex items-center gap-1.5 ${
                  catMode === 'articulos' ? 'bg-theme-accent text-theme-inverse' : 'bg-theme-surface text-theme-muted hover:bg-theme-bg'
                }`}
              >
                <Package size={14} /> Artículos
              </button>
            </div>
            {catMode === 'servicios' && (
            <div className="flex flex-wrap gap-1.5 mb-3">
              <button
                type="button"
                onClick={() => setSoloFavoritos((v) => !v)}
                className={`px-3 py-1.5 text-xs font-medium rounded-full transition flex items-center gap-1 ${
                  soloFavoritos ? 'bg-theme-accent text-theme-inverse' : 'bg-theme-accent-bg text-theme-heading hover:bg-theme-bg'
                }`}
              >
                <Star size={12} fill={soloFavoritos ? 'currentColor' : 'none'} /> Favoritos
              </button>
              <button
                type="button"
                onClick={() => { setCategoria(''); setSoloFavoritos(false); }}
                className={`px-3 py-1.5 text-xs font-medium rounded-full transition ${
                  categoria === '' && !soloFavoritos ? 'bg-theme-accent text-theme-inverse' : 'bg-theme-accent-bg text-theme-heading hover:bg-theme-bg'
                }`}
              >
                Todos
              </button>
              {categorias.map((c) => (
                <button
                  key={c}
                  type="button"
                  onClick={() => { setCategoria(c); setSoloFavoritos(false); }}
                  className={`px-3 py-1.5 text-xs font-medium rounded-full transition capitalize ${
                    categoria === c ? 'bg-theme-accent text-theme-inverse' : 'bg-theme-accent-bg text-theme-heading hover:bg-theme-bg'
                  }`}
                >
                  {c}
                </button>
              ))}
            </div>
            )}

            {catalogLoading ? (
              <Skeleton count={8} className="h-16 w-full" />
            ) : catMode === 'articulos' ? (
              visiblesItems.length === 0 ? (
                <EmptyState title="Sin artículos" subtitle="No hay artículos de inventario con esta búsqueda." icon={<Package size={28} />} />
              ) : (
                <div className="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-2">
                  {visiblesItems.map((i) => (
                    <button
                      key={i.id}
                      type="button"
                      onClick={() => addItemLine(i)}
                      className="text-left p-2.5 bg-theme-bg rounded-xl border border-theme-border hover:shadow-card hover:border-theme-border-strong transition"
                    >
                      <p className="text-sm font-medium text-theme-heading leading-tight line-clamp-2 min-h-[2.4rem]" title={i.name}>
                        {i.name}
                      </p>
                      <div className="flex items-center justify-between mt-1">
                        <span className={`text-xs ${i.qty <= 0 ? 'text-rose-600' : 'text-theme-muted'}`}>{i.qty} {i.unit || 'pzas'}</span>
                        <span className="text-sm font-bold text-theme-heading">{(i.price ?? 0) > 0 ? fmtMoney(i.price!) : <span className="text-xs font-normal text-theme-muted">sin precio</span>}</span>
                      </div>
                    </button>
                  ))}
                </div>
              )
            ) : visibles.length === 0 ? (
              <EmptyState title="Sin servicios" subtitle="No hay servicios con estos filtros." icon={<Store size={28} />} />
            ) : (
              <div className="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-2">
                {visibles.map((s) => (
                  <button
                    key={s.id}
                    type="button"
                    onClick={() => addLine(s)}
                    className="text-left p-2.5 bg-theme-bg rounded-xl border border-theme-border hover:shadow-card hover:border-theme-border-strong transition"
                  >
                    <p className="text-sm font-medium text-theme-heading leading-tight line-clamp-2 min-h-[2.4rem]" title={s.name}>
                      {s.name}
                    </p>
                    <div className="flex items-center justify-between mt-1">
                      <span className="text-xs text-theme-muted">{s.duration_min} min</span>
                      <span className="text-sm font-bold text-theme-heading">{fmtMoney(s.price)}</span>
                    </div>
                  </button>
                ))}
              </div>
            )}
          </Card.Body>
        </Card>

        {/* Ticket desktop: panel sticky full-height */}
        <Card className="hidden lg:flex lg:flex-col w-[390px] shrink-0 sticky top-6 max-h-[calc(100vh-7rem)]">
          <div className="p-4 pb-3 border-b border-theme-border shrink-0">
            <div className="flex items-center justify-between mb-2.5">
              <h3 className="font-heading text-lg text-theme-heading">Ticket</h3>
              {lines.length > 0 && (
                <Button variant="ghost" size="sm" onClick={limpiarTicket} title="Vaciar ticket">
                  <Trash2 size={15} className="text-theme-muted" />
                </Button>
              )}
            </div>
            {pacienteBlock}
          </div>
          <div className="flex-1 min-h-0 overflow-y-auto px-4 py-1">
            {linesBlock}
          </div>
          <div className="p-4 pt-3 border-t border-theme-border shrink-0 space-y-2">
            {totalsBlock}
          </div>
        </Card>
      </div>

      {/* Botón flotante móvil */}
      {lines.length > 0 && (
        <button
          type="button"
          onClick={() => setTicketMovil(true)}
          className="lg:hidden fixed bottom-4 right-4 z-30 px-5 py-3 rounded-full bg-theme-accent text-theme-inverse shadow-card font-semibold text-sm"
        >
          Ver ticket ({numItems}) {fmtMoney(total)}
        </button>
      )}

      {/* Ticket móvil */}
      <Modal isOpen={ticketMovil} onClose={() => setTicketMovil(false)} title="Ticket" maxWidth="md">
        <div className="space-y-3">
          {pacienteBlock}
          <div className="max-h-[38vh] overflow-y-auto">{linesBlock}</div>
          <div className="border-t border-theme-border pt-3 space-y-2">{totalsBlock}</div>
        </div>
      </Modal>

      {/* Modal de cobro */}
      <Modal
        isOpen={cobroOpen}
        onClose={() => setCobroOpen(false)}
        title={`Cobrar ${fmtMoney(total)}`}
        maxWidth="md"
        footer={
          <>
            <Button variant="outline" onClick={() => setCobroOpen(false)}>Cancelar</Button>
            <Button onClick={cobrar} loading={cobrando}>Confirmar cobro</Button>
          </>
        }
      >
        <div className="space-y-4">
          <Select label="Método de pago" options={METODO_OPTIONS} value={metodo} onChange={(e) => setMetodo(e.target.value)} />
          {metodo === 'cash' && !conPuntos && (
            <>
              <div>
                <p className="block text-xs font-medium mb-1.5 text-theme-muted">Moneda</p>
                <div className="inline-flex rounded-full border border-theme-border-strong overflow-hidden">
                  <button
                    type="button"
                    onClick={() => setMoneda('MXN')}
                    className={`px-4 py-1.5 text-sm font-medium transition ${
                      moneda === 'MXN' ? 'bg-theme-accent text-theme-inverse' : 'bg-theme-surface text-theme-muted hover:bg-theme-bg'
                    }`}
                  >
                    MXN
                  </button>
                  <button
                    type="button"
                    onClick={() => tcRate && setMoneda('USD')}
                    disabled={!tcRate}
                    title={!tcRate ? 'Configura el tipo de cambio en Configuración' : undefined}
                    className={`px-4 py-1.5 text-sm font-medium transition ${
                      moneda === 'USD' ? 'bg-theme-accent text-theme-inverse' : 'bg-theme-surface text-theme-muted hover:bg-theme-bg'
                    } ${!tcRate ? 'opacity-40 cursor-not-allowed' : ''}`}
                  >
                    USD
                  </button>
                </div>
                {moneda === 'USD' && tcRate && (
                  <p className="text-xs text-theme-muted mt-1.5">Tipo de cambio: {tcRate.toFixed(2)} MXN por 1 USD</p>
                )}
              </div>
              <Input
                label={moneda === 'USD' ? 'Recibido (USD)' : 'Recibido'}
                type="number"
                min={0}
                step={10}
                value={recibido}
                onChange={(e) => setRecibido(e.target.value)}
                placeholder={moneda === 'USD' && tcRate ? (total / tcRate).toFixed(2) : String(total)}
              />
              {moneda === 'USD' && recibido && tcRate && (
                <p className="text-sm text-theme-muted">≈ {fmtMoney(recibidoMxn)} MXN</p>
              )}
              {recibido && (
                <p className="text-sm">
                  <span className="text-theme-muted">Cambio: </span>
                  <span className={`font-semibold ${cambio > 0 ? 'text-theme-heading' : 'text-theme-muted'}`}>
                    {fmtMoney(cambio)}
                    {moneda === 'USD' && cambio > 0 && (
                      <span className="text-theme-muted font-normal"> (≈ {fmtUsd(cambioUsd)})</span>
                    )}
                  </span>
                </p>
              )}
            </>
          )}
          {puedePuntos && moneda === 'MXN' && (
            <label className="flex items-center gap-3 p-3 border border-theme-border-strong rounded-xl cursor-pointer hover:bg-theme-bg">
              <input
                type="checkbox"
                checked={conPuntos}
                onChange={(e) => setConPuntos(e.target.checked)}
                className="w-4 h-4 rounded border-theme-border-strong"
              />
              <span className="text-sm text-theme-heading flex items-center gap-1.5">
                <Wallet size={15} className="text-theme-muted" />
                Pagar con puntos ({puntosPaciente} pts disponibles)
              </span>
            </label>
          )}
          {conPuntos && (
            <p className="text-xs text-theme-muted">
              Se canjearán {Math.ceil(total)} pts (1 pt = $1). El paciente acumula puntos solo por lo pagado en dinero.
            </p>
          )}
        </div>
      </Modal>

      {/* Ticket de éxito */}
      <Modal
        isOpen={!!resultado}
        onClose={nuevaVenta}
        title="Venta cobrada"
        maxWidth="md"
        footer={
          <>
            <Button variant="outline" onClick={() => window.print()}>
              <Printer size={16} className="mr-2" /> Imprimir
            </Button>
            <Button onClick={nuevaVenta}>Nueva venta</Button>
          </>
        }
      >
        {resultado && (
          <div className="print-ticket text-sm">
            <div className="text-center border-b border-dashed border-theme-border pb-3 mb-3">
              <p className="font-heading font-bold text-theme-heading">SKEEN Derma Experts</p>
              <p className="text-xs text-theme-muted">Playas de Rosarito, B.C.</p>
            </div>
            <div className="flex justify-between text-xs text-theme-muted mb-2">
              <span>{resultado.sale.name}</span>
              <span>{resultado.sale.date}</span>
            </div>
            <p className="text-sm mb-3"><span className="text-theme-muted">Paciente: </span><span className="font-medium text-theme-heading">{resultado.sale.patient}</span></p>
            <table className="w-full text-sm mb-3">
              <tbody>
                {resultado.sale.lines.map((l) => (
                  <tr key={l.id}>
                    <td className="py-1 text-theme-heading">{l.quantity} × {l.service || l.item || l.description}</td>
                    <td className="py-1 text-right text-theme-heading">{fmtMoney(l.subtotal)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            <div className="border-t border-dashed border-theme-border pt-2 space-y-1 text-sm">
              <div className="flex justify-between"><span className="text-theme-muted">Subtotal</span><span>{fmtMoney(resultado.sale.subtotal)}</span></div>
              {resultado.sale.discount > 0 && (
                <div className="flex justify-between"><span className="text-theme-muted">Descuento</span><span>-{fmtMoney(resultado.sale.discount)}</span></div>
              )}
              {resultado.puntos_usados > 0 && (
                <div className="flex justify-between"><span className="text-theme-muted">Puntos canjeados</span><span>-{resultado.puntos_usados} pts</span></div>
              )}
              <div className="flex justify-between font-bold text-theme-heading"><span>Total</span><span>{fmtMoney(resultado.sale.total)}</span></div>
              <div className="flex justify-between"><span className="text-theme-muted">Método</span><span>{resultado.payment ? metodoLabel(resultado.payment.payment_method) : 'Puntos'}</span></div>
              {resultado.recibido_usd && resultado.recibido_usd > 0 && resultado.rate_used && (
                <div className="flex justify-between"><span className="text-theme-muted">Recibido USD</span><span>{fmtUsd(resultado.recibido_usd)} (TC {resultado.rate_used.toFixed(2)})</span></div>
              )}
              {resultado.cambio > 0 && (
                <div className="flex justify-between">
                  <span className="text-theme-muted">Cambio</span>
                  <span>
                    {fmtMoney(resultado.cambio)}
                    {resultado.cambio_usd && resultado.cambio_usd > 0 && (
                      <span className="text-theme-muted"> · {fmtUsd(resultado.cambio_usd)}</span>
                    )}
                  </span>
                </div>
              )}
              {resultado.puntos_ganados > 0 && (
                <div className="flex justify-between"><span className="text-theme-muted">Puntos ganados</span><span>+{resultado.puntos_ganados} pts</span></div>
              )}
              <div className="flex justify-between"><span className="text-theme-muted">Saldo monedero</span><span>{resultado.wallet_points} pts</span></div>
            </div>
            <p className="text-center text-xs text-theme-muted mt-4">¡Gracias por su visita!</p>
          </div>
        )}
      </Modal>
    </Layout>
  );
};

export default Pos;
