import type { FC } from 'react';
import { useEffect, useState, useCallback } from 'react';
import { Plus, Trash2, CreditCard, ShoppingCart, Search, Undo2, Download } from 'lucide-react';
import Layout from '../components/Layout';
import {
  Card,
  Button,
  Select,
  Input,
  TextArea,
  Modal,
  Badge,
  EmptyState,
  PageHeader,
  Skeleton,
  MobileCard,
  toast,
  badgeForSaleState,
} from '../components/ui';
import { odooApi, type Sale, type SaleLine, type Service, type Patient, type Doctor } from '../services/odoo';
import { exportToExcel } from '../lib/exporter';

interface LineForm {
  service_id: string;
  description: string;
  quantity: string;
  price_unit: string;
  is_prescribed: boolean;
  prescribed_by_id: string;
}

const emptyLine = (): LineForm => ({
  service_id: '', description: '', quantity: '1', price_unit: '',
  is_prescribed: false, prescribed_by_id: '',
});

const paymentMethods = ['Efectivo', 'Tarjeta', 'Transferencia', 'MercadoPago'];

const Ventas: FC = () => {
  const [sales, setSales] = useState<Sale[]>([]);
  const [services, setServices] = useState<Service[]>([]);
  const [patients, setPatients] = useState<Patient[]>([]);
  const [doctors, setDoctors] = useState<Doctor[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [createOpen, setCreateOpen] = useState(false);
  const [payOpen, setPayOpen] = useState<Sale | null>(null);
  const [patientId, setPatientId] = useState('');
  const [lines, setLines] = useState<LineForm[]>([
    emptyLine(),
  ]);
  const [submitting, setSubmitting] = useState(false);
  const [paying, setPaying] = useState(false);
  const [payMethod, setPayMethod] = useState('Efectivo');
  const [payAmount, setPayAmount] = useState('');
  const [refundOpen, setRefundOpen] = useState<Sale | null>(null);
  const [refunding, setRefunding] = useState(false);
  const [refundAmount, setRefundAmount] = useState('');
  const [refundReason, setRefundReason] = useState('');
  const [search, setSearch] = useState('');
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(50);
  const [total, setTotal] = useState(0);
  const [totalPages, setTotalPages] = useState(0);
  const [patientSearch, setPatientSearch] = useState('');

  const loadSales = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);
      const res = await odooApi.getSales({ search, page, page_size: pageSize });
      if (res.status === 'success') {
        setSales(res.sales);
        setTotal(res.total ?? 0);
        setTotalPages(res.total_pages ?? 0);
      }
    } catch (err) {
      setError('Error al cargar ventas');
      toast.error('Error al cargar ventas');
      console.error(err);
    } finally {
      setLoading(false);
    }
  }, [search, page, pageSize]);

  const loadRefs = useCallback(async () => {
    try {
      const servicesRes = await odooApi.getServices();
      if (servicesRes.status === 'success') setServices(servicesRes.services);
    } catch (err) {
      console.error(err);
    }
    try {
      const doctorsRes = await odooApi.getDoctors();
      if (doctorsRes.status === 'success') setDoctors(doctorsRes.doctors);
    } catch (err) {
      console.error(err);
    }
  }, []);

  useEffect(() => {
    loadRefs();
  }, [loadRefs]);

  useEffect(() => {
    loadSales();
  }, [loadSales]);

  useEffect(() => {
    setPage(1);
  }, [search]);

  // Cargar pacientes para el selector (búsqueda server-side)
  useEffect(() => {
    if (!createOpen) return;
    const t = setTimeout(async () => {
      try {
        const res = await odooApi.getPatients({ search: patientSearch, page_size: 50 });
        if (res.status === 'success') setPatients(res.patients);
      } catch (err) {
        console.error(err);
      }
    }, 250);
    return () => clearTimeout(t);
  }, [createOpen, patientSearch]);

  const addLine = () =>
    setLines([...lines, emptyLine()]);

  const removeLine = (index: number) => setLines(lines.filter((_, i) => i !== index));

  const updateLine = (index: number, field: keyof LineForm, value: string | boolean) => {
    const next = [...lines];
    next[index] = { ...next[index], [field]: value };
    setLines(next);
  };

  const create = async () => {
    if (!patientId) {
      toast.error('Selecciona un paciente');
      return;
    }
    const parsedLines: Omit<SaleLine, 'subtotal'>[] = lines
      .filter((l) => l.service_id)
      .map((l): Omit<SaleLine, 'subtotal'> | null => {
        const qty = parseFloat(l.quantity);
        const price = parseFloat(l.price_unit);
        if (Number.isNaN(qty) || qty <= 0 || Number.isNaN(price) || price < 0) {
          return null;
        }
        return {
          service_id: parseInt(l.service_id, 10),
          description: l.description,
          quantity: qty,
          price_unit: price,
          is_prescribed: l.is_prescribed,
          prescribed_by_id: l.is_prescribed && l.prescribed_by_id ? parseInt(l.prescribed_by_id, 10) : null,
        };
      })
      .filter((l): l is Omit<SaleLine, 'subtotal'> => l !== null);

    if (parsedLines.some((l) => l === null)) {
      toast.error('Revisa cantidades y precios de las líneas');
      return;
    }
    if (parsedLines.length === 0) {
      toast.error('Agrega al menos una línea');
      return;
    }

    try {
      setSubmitting(true);
      await odooApi.createSale({
        patient_id: parseInt(patientId, 10),
        lines: parsedLines,
      });
      toast.success('Venta creada');
      setCreateOpen(false);
      setPatientId('');
      setLines([emptyLine()]);
      await loadSales();
    } catch (err) {
      toast.error('Error al crear venta');
      console.error(err);
    } finally {
      setSubmitting(false);
    }
  };

  const openPay = (sale: Sale) => {
    setPayOpen(sale);
    setPayMethod('Efectivo');
    setPayAmount(String(sale.amount_due));
  };

  const pay = async () => {
    if (!payOpen) return;
    const amount = payAmount ? parseFloat(payAmount) : undefined;
    if (amount !== undefined && (Number.isNaN(amount) || amount <= 0)) {
      toast.error('Monto inválido');
      return;
    }
    try {
      setPaying(true);
      await odooApi.paySale(payOpen.id, { payment_method: payMethod, amount });
      toast.success('Pago registrado');
      setPayOpen(null);
      await loadSales();
    } catch (err) {
      toast.error('Error al pagar venta');
      console.error(err);
    } finally {
      setPaying(false);
    }
  };

  const openRefund = (sale: Sale) => {
    setRefundOpen(sale);
    setRefundAmount(String(sale.amount_paid));
    setRefundReason('');
  };

  const submitRefund = async () => {
    if (!refundOpen) return;
    const amount = refundAmount ? parseFloat(refundAmount) : undefined;
    if (amount !== undefined && (Number.isNaN(amount) || amount <= 0)) {
      toast.error('Monto inválido');
      return;
    }
    if (amount !== undefined && amount > refundOpen.amount_paid) {
      toast.error(`El monto no puede exceder lo pagado ($${refundOpen.amount_paid})`);
      return;
    }
    try {
      setRefunding(true);
      const res = await odooApi.refundSale(refundOpen.id, { amount, reason: refundReason || undefined });
      const pts = res.result?.points_reversed ?? 0;
      toast.success(`Devolución registrada${pts > 0 ? ` · ${pts} pts revertidos` : ''}`);
      setRefundOpen(null);
      await loadSales();
    } catch (err) {
      toast.error('Error al registrar devolución');
      console.error(err);
    } finally {
      setRefunding(false);
    }
  };

  const exportSales = async () => {
    try {
      await exportToExcel({
        filename: `ventas-skeen-${new Date().toISOString().split('T')[0]}`,
        sheetName: 'Ventas',
        title: 'Ventas SKEEN',
        subtitle: `${sales.length} ventas de la vista actual`,
        columns: [
          { header: 'Referencia', key: 'name' },
          { header: 'Paciente', key: 'patient' },
          { header: 'Fecha', key: 'date', format: 'date' },
          { header: 'Subtotal', key: 'subtotal', format: 'currency' },
          { header: 'Descuento', key: 'discount', format: 'currency' },
          { header: 'Impuesto', key: 'tax', format: 'currency' },
          { header: 'Total', key: 'total', format: 'currency' },
          { header: 'Pagado', key: 'amount_paid', format: 'currency' },
          { header: 'Por cobrar', key: 'amount_due', format: 'currency' },
          { header: 'Estado', key: 'state' },
          { header: 'Devuelta', key: 'devuelta' },
          { header: 'Monto devuelto', key: 'refund_amount', format: 'currency' },
        ],
        rows: sales.map((s) => ({ ...s, devuelta: s.refunded ? 'Sí' : 'No', refund_amount: s.refund_amount || 0 })),
        totals: {
          name: '', total: sales.reduce((a, s) => a + s.total, 0),
          amount_paid: sales.reduce((a, s) => a + s.amount_paid, 0),
          amount_due: sales.reduce((a, s) => a + s.amount_due, 0),
          refund_amount: sales.reduce((a, s) => a + (s.refund_amount || 0), 0),
        },
      });
      toast.success(`Excel descargado (${sales.length} ventas de la vista actual)`);
    } catch (err) {
      toast.error('Error al exportar');
      console.error(err);
    }
  };

  const patientOptions = [
    { value: '', label: 'Seleccionar paciente...' },
    ...patients.map((p) => ({ value: String(p.id), label: `${p.name} (${p.phone})` })),
  ];

  const serviceOptions = [
    { value: '', label: 'Servicio...' },
    ...services.map((s) => ({ value: String(s.id), label: `${s.name} — $${s.price}` })),
  ];

  const doctorOptions = [
    { value: '', label: 'Médico que recetó...' },
    ...doctors.map((d) => ({ value: String(d.id), label: `${d.name} (${d.commission_pct ?? 0}%)` })),
  ];

  const payMethodOptions = paymentMethods.map((m) => ({ value: m, label: m }));

  return (
    <Layout title="Ventas" subtitle="Órdenes de venta">
      <PageHeader title="Ventas" subtitle="Crea ventas y registra pagos">
        <Button variant="outline" onClick={exportSales} disabled={sales.length === 0}>
          <Download size={16} className="mr-2" />
          Exportar CSV
        </Button>
        <Button onClick={() => setCreateOpen(true)}>
          <Plus size={16} className="mr-2" />
          Nueva venta
        </Button>
      </PageHeader>

      <Card>
        <Card.Body>
          <div className="flex flex-col sm:flex-row sm:items-center gap-3 mb-4 sm:mb-6">
            <div className="relative w-full sm:max-w-sm">
              <Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-theme-muted" />
              <Input
                placeholder="Buscar por referencia o paciente..."
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                className="pl-10"
              />
            </div>
          </div>

          {error && <p className="text-rose-600 text-sm mb-4">{error}</p>}

          {loading ? (
            <Skeleton count={6} className="h-12 w-full" />
          ) : sales.length === 0 ? (
            <EmptyState
              title="Sin ventas"
              subtitle="No hay ventas registradas."
              actionLabel="Nueva venta"
              onAction={() => setCreateOpen(true)}
              icon={<ShoppingCart size={28} />}
            />
          ) : (
            <>
              <div className="hidden sm:block overflow-x-auto">
                <table className="w-full">
                  <thead className="bg-theme-bg">
                    <tr>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase">Referencia</th>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase">Paciente</th>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase">Total</th>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase hidden md:table-cell">Pagado</th>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase">Estado</th>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase">Acciones</th>
                    </tr>
                  </thead>
                  <tbody className="divide-y">
                    {sales.map((s) => (
                      <tr key={s.id} className="hover:bg-theme-bg">
                        <td className="p-3 text-sm text-theme-muted">{s.name}</td>
                        <td className="p-3 text-sm font-medium text-theme-heading">{s.patient}</td>
                        <td className="p-3 text-sm font-semibold text-theme-heading">${s.total}</td>
                        <td className="p-3 text-sm text-theme-muted hidden md:table-cell">${s.amount_paid}</td>
                        <td className="p-3">
                          <div className="flex items-center gap-2">
                            <Badge variant={badgeForSaleState(s.state)}>{s.state}</Badge>
                            {s.refunded && <Badge variant="warning">Devuelta</Badge>}
                          </div>
                        </td>
                        <td className="p-3">
                          <div className="flex items-center gap-1">
                            {s.amount_due > 0 && (
                              <Button variant="ghost" size="sm" onClick={() => openPay(s)} title="Pagar">
                                <CreditCard size={16} className="text-theme-heading mr-1.5" />
                                Pagar
                              </Button>
                            )}
                            {s.amount_paid > 0 && s.state !== 'cancelled' && (
                              <Button variant="ghost" size="sm" onClick={() => openRefund(s)} title="Devolución">
                                <Undo2 size={16} className="text-amber-600 mr-1.5" />
                                Devolución
                              </Button>
                            )}
                          </div>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>

              <div className="sm:hidden space-y-3">
                {sales.map((s) => (
                  <MobileCard
                    key={s.id}
                    title={s.patient}
                    subtitle={s.name}
                    rows={[
                      { label: 'Total', value: `$${s.total}` },
                      { label: 'Pagado', value: `$${s.amount_paid}` },
                      {
                        label: 'Estado',
                        value: (
                          <div className="flex items-center gap-2">
                            <Badge variant={badgeForSaleState(s.state)}>{s.state}</Badge>
                            {s.refunded && <Badge variant="warning">Devuelta</Badge>}
                          </div>
                        ),
                      },
                    ]}
                    actions={
                      <div className="flex items-center gap-1">
                        {s.amount_due > 0 && (
                          <Button variant="ghost" size="sm" onClick={() => openPay(s)}>
                            <CreditCard size={16} className="text-theme-heading" />
                          </Button>
                        )}
                        {s.amount_paid > 0 && s.state !== 'cancelled' && (
                          <Button variant="ghost" size="sm" onClick={() => openRefund(s)} title="Devolución">
                            <Undo2 size={16} className="text-amber-600" />
                          </Button>
                        )}
                      </div>
                    }
                  />
                ))}
              </div>

              {/* Paginación */}
              <div className="flex flex-col sm:flex-row items-center justify-between gap-3 mt-4 pt-4 border-t border-theme-border">
                <p className="text-sm text-theme-muted">
                  {total} ventas · página {page} de {totalPages || 1}
                </p>
                <div className="flex items-center gap-2">
                  <select
                    value={pageSize}
                    onChange={(e) => { setPageSize(parseInt(e.target.value, 10)); setPage(1); }}
                    className="border border-theme-border-strong rounded-lg px-2 py-1.5 text-sm"
                  >
                    <option value={25}>25</option>
                    <option value={50}>50</option>
                    <option value={100}>100</option>
                    <option value={200}>200</option>
                  </select>
                  <Button variant="outline" size="sm" disabled={page <= 1} onClick={() => setPage((p) => Math.max(1, p - 1))}>
                    Anterior
                  </Button>
                  <Button variant="outline" size="sm" disabled={page >= totalPages} onClick={() => setPage((p) => p + 1)}>
                    Siguiente
                  </Button>
                </div>
              </div>
            </>
          )}
        </Card.Body>
      </Card>

      <Modal
        isOpen={createOpen}
        onClose={() => setCreateOpen(false)}
        title="Nueva venta"
        maxWidth="2xl"
        footer={
          <>
            <Button variant="outline" onClick={() => setCreateOpen(false)}>Cancelar</Button>
            <Button onClick={create} loading={submitting}>Crear venta</Button>
          </>
        }
      >
        <div className="space-y-4">
          <Input
            label="Buscar paciente"
            placeholder="Escribe nombre o teléfono..."
            value={patientSearch}
            onChange={(e) => setPatientSearch(e.target.value)}
          />
          <Select
            label="Paciente *"
            options={patientOptions}
            value={patientId}
            onChange={(e) => setPatientId(e.target.value)}
          />

          <div>
            <div className="flex items-center justify-between mb-2">
              <label className="text-xs font-medium text-theme-muted">Líneas</label>
              <Button variant="outline" size="sm" onClick={addLine}>
                <Plus size={14} className="mr-1" />
                Agregar
              </Button>
            </div>
            <div className="space-y-2">
              {lines.map((line, i) => (
                <div key={i} className="space-y-2">
                  <div className="grid grid-cols-12 gap-2 items-start">
                  <div className="col-span-12 sm:col-span-4">
                    <Select
                      options={serviceOptions}
                      value={line.service_id}
                      onChange={(e) => {
                        const sid = e.target.value;
                        const svc = services.find((s) => String(s.id) === sid);
                        updateLine(i, 'service_id', sid);
                        if (svc) {
                          updateLine(i, 'price_unit', String(svc.price));
                          updateLine(i, 'description', svc.name);
                        }
                      }}
                    />
                  </div>
                  <Input
                    placeholder="Descripción"
                    value={line.description}
                    onChange={(e) => updateLine(i, 'description', e.target.value)}
                    className="col-span-12 sm:col-span-4"
                  />
                  <Input
                    type="number"
                    placeholder="Cant"
                    value={line.quantity}
                    onChange={(e) => updateLine(i, 'quantity', e.target.value)}
                    className="col-span-4 sm:col-span-1"
                  />
                  <Input
                    type="number"
                    placeholder="Precio"
                    value={line.price_unit}
                    onChange={(e) => updateLine(i, 'price_unit', e.target.value)}
                    className="col-span-6 sm:col-span-2"
                  />
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => removeLine(i)}
                    className="col-span-2 sm:col-span-1 h-[42px]"
                    title="Eliminar línea"
                  >
                    <Trash2 size={16} className="text-rose-600" />
                  </Button>
                  </div>
                  <div className="flex flex-col sm:flex-row sm:items-center gap-2 pl-1">
                    <label className="inline-flex items-center gap-2 text-sm text-theme-muted cursor-pointer">
                      <input
                        type="checkbox"
                        checked={line.is_prescribed}
                        onChange={(e) => updateLine(i, 'is_prescribed', e.target.checked)}
                        className="rounded border-theme-border-strong"
                      />
                      Artículo recetado
                    </label>
                    {line.is_prescribed && (
                      <Select
                        options={doctorOptions}
                        value={line.prescribed_by_id}
                        onChange={(e) => updateLine(i, 'prescribed_by_id', e.target.value)}
                        className="sm:max-w-xs"
                      />
                    )}
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </Modal>

      <Modal
        isOpen={!!payOpen}
        onClose={() => setPayOpen(null)}
        title={`Pagar ${payOpen?.name || ''}`}
        maxWidth="sm"
        footer={
          <>
            <Button variant="outline" onClick={() => setPayOpen(null)}>Cancelar</Button>
            <Button onClick={pay} loading={paying}>Registrar pago</Button>
          </>
        }
      >
        {payOpen && (
          <div className="space-y-4">
            <p className="text-sm text-theme-muted">
              Paciente: <span className="font-medium text-theme-heading">{payOpen.patient}</span>
            </p>
            <p className="text-sm text-theme-muted">
              Total: <span className="font-medium text-theme-heading">${payOpen.total}</span>
              {' · '}
              Por pagar: <span className="font-medium text-theme-heading">${payOpen.amount_due}</span>
            </p>
            <Select
              label="Método de pago"
              options={payMethodOptions}
              value={payMethod}
              onChange={(e) => setPayMethod(e.target.value)}
            />
            <Input
              label="Monto"
              type="number"
              min={0.01}
              step={0.01}
              value={payAmount}
              onChange={(e) => setPayAmount(e.target.value)}
            />
          </div>
        )}
      </Modal>

      <Modal
        isOpen={!!refundOpen}
        onClose={() => setRefundOpen(null)}
        title={`Devolución ${refundOpen?.name || ''}`}
        maxWidth="sm"
        footer={
          <>
            <Button variant="outline" onClick={() => setRefundOpen(null)}>Cancelar</Button>
            <Button variant="danger" onClick={submitRefund} loading={refunding}>Confirmar devolución</Button>
          </>
        }
      >
        {refundOpen && (
          <div className="space-y-4">
            <p className="text-sm text-theme-muted">
              Paciente: <span className="font-medium text-theme-heading">{refundOpen.patient}</span>
            </p>
            <p className="text-sm text-theme-muted">
              Total: <span className="font-medium text-theme-heading">${refundOpen.total}</span>
              {' · '}
              Pagado: <span className="font-medium text-theme-heading">${refundOpen.amount_paid}</span>
            </p>
            <div className="rounded-lg bg-amber-50 border border-theme-bg px-3 py-2 text-xs text-amber-800">
              La devolución reduce el monto pagado y revierte los puntos del monedero en proporción ($10 = 1 pt). Deja el monto vacío o igual a lo pagado para devolución total.
            </div>
            <Input
              label="Monto a devolver"
              type="number"
              min={0.01}
              max={refundOpen.amount_paid}
              step={0.01}
              value={refundAmount}
              onChange={(e) => setRefundAmount(e.target.value)}
            />
            <TextArea
              label="Motivo"
              placeholder="Motivo de la devolución..."
              value={refundReason}
              onChange={(e) => setRefundReason(e.target.value)}
            />
          </div>
        )}
      </Modal>
    </Layout>
  );
};

export default Ventas;
