import type { FC } from 'react';
import { useEffect, useState, useCallback, useRef } from 'react';
import { ClipboardList, CheckCircle2, XCircle, X, Plus, Camera, FileText } from 'lucide-react';
import Layout from '../components/Layout';
import { RecetaSection, RecetaPrint } from '../components/RecetaPrint';
import {
  Card,
  Button,
  Input,
  Select,
  TextArea,
  Modal,
  Badge,
  EmptyState,
  MobileCard,
  PageHeader,
  Skeleton,
  toast,
} from '../components/ui';
import { odooApi, type Visita, type VisitaAdjunto, type Doctor, type InventoryItem } from '../services/odoo';
import type { BadgeVariant } from '../components/ui/Badge';

const visitaStateLabels: Record<string, string> = {
  en_curso: 'En curso',
  completada: 'Completada',
  cancelada: 'Cancelada',
};

const badgeForVisitaState = (state: string): BadgeVariant =>
  state === 'en_curso' ? 'info' : state === 'completada' ? 'success' : state === 'cancelada' ? 'danger' : 'default';

const estadoOptions = [
  { value: '', label: 'Todos' },
  { value: 'en_curso', label: 'En curso' },
  { value: 'completada', label: 'Completada' },
  { value: 'cancelada', label: 'Cancelada' },
];

const adjuntoKindLabels: Record<string, string> = {
  antes: 'Antes',
  despues: 'Después',
  documento: 'Documento',
};

const MAX_ADJUNTO_BYTES = 10 * 1024 * 1024;

const hoy = () => new Date().toISOString().split('T')[0];

const Visitas: FC = () => {
  const [visitas, setVisitas] = useState<Visita[]>([]);
  const [doctors, setDoctors] = useState<Doctor[]>([]);
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [fecha, setFecha] = useState(hoy());
  const [estado, setEstado] = useState('');
  const [doctorFiltro, setDoctorFiltro] = useState('');
  const [selected, setSelected] = useState<Visita | null>(null);
  const [form, setForm] = useState({
    motivo: '',
    diagnostico: '',
    tratamiento: '',
    notas: '',
    receta_text: '',
    doctor_id: '',
    cosmetologa_id: '',
  });
  const [printOpen, setPrintOpen] = useState(false);
  const [items, setItems] = useState<InventoryItem[]>([]);
  const [itemSearch, setItemSearch] = useState('');
  const [nuevoItem, setNuevoItem] = useState('');
  const [nuevaQty, setNuevaQty] = useState('1');
  const [visor, setVisor] = useState<VisitaAdjunto | null>(null);
  const fileAntesRef = useRef<HTMLInputElement>(null);
  const fileDespuesRef = useRef<HTMLInputElement>(null);
  const fileDocRef = useRef<HTMLInputElement>(null);

  const doctorOptions = [
    { value: '', label: 'Sin asignar' },
    ...doctors.map((d) => ({ value: String(d.id), label: d.name })),
  ];

  const load = useCallback(async () => {
    try {
      setLoading(true);
      const params: Record<string, string | number> = {};
      if (fecha) params.date = fecha;
      if (estado) params.state = estado;
      if (doctorFiltro) params.doctor_id = doctorFiltro;
      const res = await odooApi.getVisitas(params);
      if (res.status === 'success') setVisitas(res.visitas);
    } catch (err) {
      toast.error('Error al cargar visitas');
      console.error(err);
    } finally {
      setLoading(false);
    }
  }, [fecha, estado, doctorFiltro]);

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

  useEffect(() => {
    odooApi.getDoctors()
      .then((res) => {
        if (res.status === 'success') setDoctors(res.doctors);
      })
      .catch(() => {});
  }, []);

  // Catálogo de artículos del inventario para el picker de insumos
  useEffect(() => {
    if (!selected || selected.state !== 'en_curso') return;
    odooApi.getInventarioItems(itemSearch || undefined)
      .then((res) => {
        if (res.status === 'success') setItems(res.items);
      })
      .catch(() => {});
  }, [selected, itemSearch]);

  const itemOptions = [
    { value: '', label: 'Selecciona artículo...' },
    ...items.map((it) => ({ value: String(it.id), label: `${it.name} (${it.qty} ${it.unit})` })),
  ];

  const agregarInsumo = async () => {
    if (!selected || !nuevoItem) return;
    const qty = parseFloat(nuevaQty);
    if (Number.isNaN(qty) || qty <= 0) {
      toast.error('La cantidad debe ser mayor a 0');
      return;
    }
    try {
      setSubmitting(true);
      const res = await odooApi.addVisitaInsumo(selected.id, { item_id: parseInt(nuevoItem, 10), qty });
      if (res.status === 'success') {
        applyUpdate(res.visita);
        setNuevoItem('');
        setNuevaQty('1');
        toast.success('Insumo agregado');
      }
    } catch (err) {
      toast.error('Error al agregar insumo');
      console.error(err);
    } finally {
      setSubmitting(false);
    }
  };

  const quitarInsumo = async (lineId: number) => {
    if (!selected) return;
    try {
      setSubmitting(true);
      const res = await odooApi.deleteVisitaInsumo(selected.id, lineId);
      if (res.status === 'success') applyUpdate(res.visita);
    } catch (err) {
      toast.error('Error al quitar insumo');
      console.error(err);
    } finally {
      setSubmitting(false);
    }
  };

  const subirAdjunto = (kind: 'antes' | 'despues' | 'documento') => (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    e.target.value = '';
    if (!file || !selected) return;
    if (file.size > MAX_ADJUNTO_BYTES) {
      toast.error('El archivo excede 10 MB');
      return;
    }
    const visitaId = selected.id;
    const reader = new FileReader();
    reader.onload = async () => {
      const file_b64 = String(reader.result || '').split(',')[1] || '';
      try {
        setSubmitting(true);
        const res = await odooApi.uploadVisitaAdjunto(visitaId, {
          kind,
          name: file.name,
          file_b64,
          mimetype: file.type || 'application/octet-stream',
        });
        if (res.status === 'success') {
          applyUpdate(res.visita);
          toast.success('Archivo subido');
        }
      } catch (err) {
        toast.error('Error al subir el archivo');
        console.error(err);
      } finally {
        setSubmitting(false);
      }
    };
    reader.readAsDataURL(file);
  };

  const borrarAdjunto = async (adjId: number) => {
    if (!window.confirm('¿Eliminar este archivo?')) return;
    try {
      setSubmitting(true);
      const res = await odooApi.deleteVisitaAdjunto(adjId);
      if (res.status === 'success') applyUpdate(res.visita);
    } catch (err) {
      toast.error('Error al eliminar el archivo');
      console.error(err);
    } finally {
      setSubmitting(false);
    }
  };

  const openDetail = (v: Visita) => {
    setSelected(v);
    setForm({
      motivo: v.motivo || '',
      diagnostico: v.diagnostico || '',
      tratamiento: v.tratamiento || '',
      notas: v.notas || '',
      receta_text: v.receta_text || '',
      doctor_id: v.doctor_id ? String(v.doctor_id) : '',
      cosmetologa_id: v.cosmetologa_id ? String(v.cosmetologa_id) : '',
    });
  };

  const updateForm = (patch: Partial<typeof form>) => {
    setForm((prev) => ({ ...prev, ...patch }));
  };

  const applyUpdate = (v: Visita) => {
    setSelected(v);
    setVisitas((prev) => prev.map((it) => (it.id === v.id ? v : it)));
  };

  const save = async () => {
    if (!selected) return;
    try {
      setSubmitting(true);
      const res = await odooApi.updateVisita(selected.id, {
        motivo: form.motivo,
        diagnostico: form.diagnostico,
        tratamiento: form.tratamiento,
        notas: form.notas,
        receta_text: form.receta_text,
        doctor_id: form.doctor_id ? parseInt(form.doctor_id, 10) : null,
        cosmetologa_id: form.cosmetologa_id ? parseInt(form.cosmetologa_id, 10) : null,
      });
      if (res.status === 'success') {
        applyUpdate(res.visita);
        toast.success('Visita actualizada');
      }
    } catch (err) {
      toast.error('Error al guardar la visita');
      console.error(err);
    } finally {
      setSubmitting(false);
    }
  };

  const completar = async () => {
    if (!selected) return;
    try {
      setSubmitting(true);
      const res = await odooApi.completeVisita(selected.id);
      if (res.status === 'success') {
        applyUpdate(res.visita);
        toast.success('Visita completada');
      }
    } catch (err) {
      toast.error('Error al completar la visita');
      console.error(err);
    } finally {
      setSubmitting(false);
    }
  };

  const cancelar = async () => {
    if (!selected) return;
    try {
      setSubmitting(true);
      const res = await odooApi.cancelVisita(selected.id);
      if (res.status === 'success') {
        applyUpdate(res.visita);
        toast.success('Visita cancelada');
      }
    } catch (err) {
      toast.error('Error al cancelar la visita');
      console.error(err);
    } finally {
      setSubmitting(false);
    }
  };

  const hora = (v: Visita) => (v.date_start ? v.date_start.split(' ')[1] || '' : '-');

  return (
    <Layout title="Visitas" subtitle="Registro de visitas clínicas">
      <PageHeader title="Visitas" subtitle="Consulta y completa las visitas clínicas del día" />

      <Card>
        <Card.Body>
          <div className="grid grid-cols-1 sm:grid-cols-3 gap-3 mb-4 sm:mb-6">
            <Input label="Fecha" type="date" value={fecha} onChange={(e) => setFecha(e.target.value)} />
            <Select label="Estado" options={estadoOptions} value={estado} onChange={(e) => setEstado(e.target.value)} />
            <Select
              label="Médico"
              options={[{ value: '', label: 'Todos' }, ...doctorOptions.slice(1)]}
              value={doctorFiltro}
              onChange={(e) => setDoctorFiltro(e.target.value)}
            />
          </div>

          {loading ? (
            <Skeleton count={6} className="h-12 w-full" />
          ) : visitas.length === 0 ? (
            <EmptyState
              title={fecha === hoy() ? 'Sin visitas hoy' : 'Sin visitas'}
              subtitle="No se encontraron visitas con los filtros seleccionados."
              icon={<ClipboardList 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">Hora</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 hidden md:table-cell">Servicio</th>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase hidden md:table-cell">Médico</th>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase hidden lg:table-cell">Motivo</th>
                      <th className="text-left p-3 text-xs font-medium text-theme-muted uppercase">Estado</th>
                    </tr>
                  </thead>
                  <tbody className="divide-y">
                    {visitas.map((v) => (
                      <tr key={v.id} className="hover:bg-theme-bg cursor-pointer" onClick={() => openDetail(v)}>
                        <td className="p-3 text-sm text-theme-muted">{hora(v)}</td>
                        <td className="p-3 text-sm font-medium text-theme-heading">{v.patient}</td>
                        <td className="p-3 text-sm text-theme-muted hidden md:table-cell">{v.servicio || '-'}</td>
                        <td className="p-3 text-sm text-theme-muted hidden md:table-cell">{v.doctor || '-'}</td>
                        <td className="p-3 text-sm text-theme-muted hidden lg:table-cell truncate max-w-[200px]">{v.motivo || '-'}</td>
                        <td className="p-3 text-sm">
                          <Badge variant={badgeForVisitaState(v.state)}>
                            {visitaStateLabels[v.state] || v.state}
                          </Badge>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>

              <div className="sm:hidden space-y-3">
                {visitas.map((v) => (
                  <MobileCard
                    key={v.id}
                    title={v.patient}
                    subtitle={hora(v)}
                    rows={[
                      { label: 'Servicio', value: v.servicio || '-' },
                      { label: 'Médico', value: v.doctor || '-' },
                      {
                        label: 'Estado',
                        value: (
                          <Badge variant={badgeForVisitaState(v.state)}>
                            {visitaStateLabels[v.state] || v.state}
                          </Badge>
                        ),
                      },
                    ]}
                    onClick={() => openDetail(v)}
                  />
                ))}
              </div>
            </>
          )}
        </Card.Body>
      </Card>

      {/* Modal detalle/edición */}
      <Modal
        isOpen={!!selected}
        onClose={() => setSelected(null)}
        title={selected ? `Visita ${selected.name} — ${selected.patient}` : 'Visita'}
        maxWidth="2xl"
        footer={
          <>
            <Button variant="outline" onClick={() => setSelected(null)}>Cerrar</Button>
            {selected?.state === 'en_curso' && (
              <Button variant="outline" onClick={cancelar} loading={submitting}>
                <XCircle size={16} className="mr-2" />
                Cancelar visita
              </Button>
            )}
            <Button onClick={save} loading={submitting}>Guardar</Button>
            {selected?.state === 'en_curso' && (
              <Button onClick={completar} loading={submitting}>
                <CheckCircle2 size={16} className="mr-2" />
                Completar visita
              </Button>
            )}
          </>
        }
      >
        {selected && (
          <div className="space-y-4 max-h-[70vh] overflow-y-auto pr-1">
            <div className="flex flex-wrap items-center gap-2">
              <Badge variant={badgeForVisitaState(selected.state)}>
                {visitaStateLabels[selected.state] || selected.state}
              </Badge>
              <span className="text-sm text-theme-muted">
                {selected.date_start || '-'}{selected.date_end ? ` → ${selected.date_end}` : ''}
              </span>
              {selected.servicio && (
                <span className="text-sm text-theme-muted">· {selected.servicio}</span>
              )}
            </div>
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
              <Select
                label="Médico"
                options={doctorOptions}
                value={form.doctor_id}
                onChange={(e) => updateForm({ doctor_id: e.target.value })}
              />
              <Select
                label="Cosmetóloga"
                options={doctorOptions}
                value={form.cosmetologa_id}
                onChange={(e) => updateForm({ cosmetologa_id: e.target.value })}
              />
            </div>
            <Input label="Motivo de consulta" value={form.motivo} onChange={(e) => updateForm({ motivo: e.target.value })} />
            <TextArea label="Diagnóstico" value={form.diagnostico} onChange={(e) => updateForm({ diagnostico: e.target.value })} />
            <TextArea label="Tratamiento" value={form.tratamiento} onChange={(e) => updateForm({ tratamiento: e.target.value })} />
            <TextArea label="Notas" value={form.notas} onChange={(e) => updateForm({ notas: e.target.value })} />

            <RecetaSection
              value={form.receta_text}
              onChange={(v) => updateForm({ receta_text: v })}
              onPrint={() => setPrintOpen(true)}
            />

            {/* Insumos usados */}
            <section className="border-t border-theme-border pt-4">
              <h4 className="text-sm font-semibold text-theme-heading mb-3">Insumos usados</h4>
              {selected.insumos_descargados && (
                <p className="text-xs text-theme-muted mb-2">Insumos descargados del inventario.</p>
              )}
              {selected.insumos.length === 0 ? (
                <p className="text-sm text-theme-muted mb-3">Sin insumos registrados.</p>
              ) : (
                <ul className="space-y-1 mb-3">
                  {selected.insumos.map((l) => (
                    <li key={l.id} className="flex items-center justify-between p-2 bg-theme-bg rounded-lg text-sm">
                      <span className="text-theme-heading">
                        {l.item}
                        {l.notes && <span className="block text-xs text-theme-muted">{l.notes}</span>}
                      </span>
                      <span className="flex items-center gap-2 shrink-0">
                        <span className="text-theme-muted">{l.qty} {l.unit}</span>
                        {selected.state === 'en_curso' && (
                          <Button variant="ghost" size="sm" onClick={() => quitarInsumo(l.id)} title="Quitar" disabled={submitting}>
                            <X size={14} className="text-theme-muted" />
                          </Button>
                        )}
                      </span>
                    </li>
                  ))}
                </ul>
              )}
              {selected.state === 'en_curso' && (
                <div className="space-y-2">
                  <Input
                    placeholder="Buscar artículo..."
                    value={itemSearch}
                    onChange={(e) => setItemSearch(e.target.value)}
                  />
                  <div className="flex items-end gap-2">
                    <div className="flex-1">
                      <Select
                        options={itemOptions}
                        value={nuevoItem}
                        onChange={(e) => setNuevoItem(e.target.value)}
                      />
                    </div>
                    <div className="w-24">
                      <Input
                        type="number"
                        min="0.5"
                        step="0.5"
                        value={nuevaQty}
                        onChange={(e) => setNuevaQty(e.target.value)}
                      />
                    </div>
                    <Button onClick={agregarInsumo} disabled={!nuevoItem} loading={submitting}>
                      <Plus size={16} className="mr-1" />
                      Agregar
                    </Button>
                  </div>
                </div>
              )}
            </section>

            {/* Fotos y documentos */}
            <section className="border-t border-theme-border pt-4">
              <h4 className="text-sm font-semibold text-theme-heading mb-3">Fotos y documentos</h4>
              {selected.state === 'en_curso' && (
                <div className="flex flex-wrap gap-2 mb-3">
                  <input ref={fileAntesRef} type="file" accept="image/*" className="hidden" onChange={subirAdjunto('antes')} />
                  <input ref={fileDespuesRef} type="file" accept="image/*" className="hidden" onChange={subirAdjunto('despues')} />
                  <input ref={fileDocRef} type="file" className="hidden" onChange={subirAdjunto('documento')} />
                  <Button variant="outline" size="sm" onClick={() => fileAntesRef.current?.click()} disabled={submitting}>
                    <Camera size={14} className="mr-1.5" /> Foto antes
                  </Button>
                  <Button variant="outline" size="sm" onClick={() => fileDespuesRef.current?.click()} disabled={submitting}>
                    <Camera size={14} className="mr-1.5" /> Foto después
                  </Button>
                  <Button variant="outline" size="sm" onClick={() => fileDocRef.current?.click()} disabled={submitting}>
                    <FileText size={14} className="mr-1.5" /> Documento
                  </Button>
                </div>
              )}
              {selected.adjuntos.length === 0 ? (
                <p className="text-sm text-theme-muted">Sin archivos adjuntos.</p>
              ) : (
                <>
                  {selected.adjuntos.filter((a) => a.kind !== 'documento').length > 0 && (
                    <div className="grid grid-cols-2 sm:grid-cols-3 gap-2 mb-3">
                      {selected.adjuntos.filter((a) => a.kind !== 'documento').map((a) => (
                        <div key={a.id} className="relative">
                          <button type="button" onClick={() => setVisor(a)} className="w-full">
                            <img
                              src={odooApi.visitaAdjuntoUrl(a.url)}
                              alt={a.name}
                              className="w-full h-24 object-cover rounded-xl border border-theme-border"
                            />
                          </button>
                          <span className="absolute bottom-1 left-1 px-1.5 py-0.5 rounded-md text-[10px] font-medium bg-theme-surface/90 text-theme-heading">
                            {adjuntoKindLabels[a.kind] || a.kind}
                          </span>
                          {selected.state === 'en_curso' && (
                            <button
                              type="button"
                              onClick={() => borrarAdjunto(a.id)}
                              title="Eliminar"
                              className="absolute top-1 right-1 p-1 rounded-full bg-theme-surface/90 text-theme-muted hover:text-rose-600"
                            >
                              <X size={12} />
                            </button>
                          )}
                        </div>
                      ))}
                    </div>
                  )}
                  {selected.adjuntos.filter((a) => a.kind === 'documento').length > 0 && (
                    <ul className="space-y-1">
                      {selected.adjuntos.filter((a) => a.kind === 'documento').map((a) => (
                        <li key={a.id} className="flex items-center justify-between p-2 bg-theme-bg rounded-lg text-sm">
                          <a
                            href={odooApi.visitaAdjuntoUrl(a.url)}
                            target="_blank"
                            rel="noreferrer"
                            className="flex items-center text-theme-heading hover:underline min-w-0"
                          >
                            <FileText size={14} className="mr-1.5 text-theme-muted shrink-0" />
                            <span className="truncate">{a.name}</span>
                          </a>
                          {selected.state === 'en_curso' && (
                            <Button variant="ghost" size="sm" onClick={() => borrarAdjunto(a.id)} title="Eliminar" disabled={submitting}>
                              <X size={14} className="text-theme-muted" />
                            </Button>
                          )}
                        </li>
                      ))}
                    </ul>
                  )}
                </>
              )}
            </section>
          </div>
        )}
      </Modal>

      {/* Visor de foto */}
      <Modal
        isOpen={!!visor}
        onClose={() => setVisor(null)}
        title={visor ? `${adjuntoKindLabels[visor.kind] || visor.kind} — ${visor.name}` : 'Foto'}
        maxWidth="2xl"
      >
        {visor && (
          <img
            src={odooApi.visitaAdjuntoUrl(visor.url)}
            alt={visor.name}
            className="w-full rounded-xl"
          />
        )}
      </Modal>

      {/* Vista de impresión de la receta */}
      {selected && (
        <RecetaPrint
          isOpen={printOpen}
          onClose={() => setPrintOpen(false)}
          paciente={selected.patient}
          doctor={selected.doctor}
          contenido={form.receta_text}
        />
      )}
    </Layout>
  );
};

export default Visitas;
