'use client';

import { DashboardSection } from '@/components/dashboard-page';
import { DataRefreshControl } from '@/components/data-refresh-control';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { ErrorState } from '@/components/ui/error-state';
import { Field } from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { Skeleton, SkeletonDetailHeader } from '@/components/ui/skeleton';
import { useFlagsConfiguracion } from '@/hooks/use-flags-configuracion';
import { useToast } from '@/hooks/use-toast';
import { otsApi, uploadFileWithProgress } from '@/lib/api';
import { db } from '@/lib/db';
import { canMutateOtRemotely, isOtLocked, OT_DETAIL_REFRESH_INTERVAL_MS, refreshOtDetail } from '@/lib/ot-detail';
import { formatDate, formatDateTime, getEstadoLabel } from '@/lib/utils';
import { normalizePrintAssetUrl } from '@/lib/print';
import { getSignatureUploadFile, useResponsiveSignaturePad } from '@/lib/signature-pad';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { ArrowLeft, Eraser, Loader2, RotateCcw, Save } from 'lucide-react';
import { useParams, useRouter } from 'next/navigation';
import { type RefObject, useEffect, useRef, useState } from 'react';
import SignatureCanvas from 'react-signature-canvas';

type SignatureStroke = any[];

function clearPad(ref: RefObject<SignatureCanvas | null>, onStore: (data: SignatureStroke[]) => void) {
  const current = ref.current;
  if (!current || current.isEmpty()) return;
  onStore(current.toData() as SignatureStroke[]);
  current.clear();
}

function undoPad(ref: RefObject<SignatureCanvas | null>) {
  const current = ref.current;
  if (!current || current.isEmpty()) return;
  const data = current.toData() as SignatureStroke[];
  current.fromData(data.slice(0, -1));
}

function restorePad(ref: RefObject<SignatureCanvas | null>, strokes: SignatureStroke[]) {
  const current = ref.current;
  if (!current || !strokes.length || !current.isEmpty()) return;
  current.fromData(strokes);
}

export default function FirmasPage() {
  const params = useParams();
  const router = useRouter();
  const { toast } = useToast();
  const queryClient = useQueryClient();
  const { usaFirmaCliente, usaFirmaRecepcion } = useFlagsConfiguracion();
  const routeId = String(params.id);
  const clienteRef = useRef<SignatureCanvas | null>(null);
  const recepcionRef = useRef<SignatureCanvas | null>(null);
  const clientePadContainerRef = useRef<HTMLDivElement | null>(null);
  const recepcionPadContainerRef = useRef<HTMLDivElement | null>(null);
  const clienteDrawingRef = useRef(false);
  const recepcionDrawingRef = useRef(false);
  const [nombreCliente, setNombreCliente] = useState('');
  const [nombreRecepcion, setNombreRecepcion] = useState('');
  const [clienteBackup, setClienteBackup] = useState<SignatureStroke[]>([]);
  const [recepcionBackup, setRecepcionBackup] = useState<SignatureStroke[]>([]);
  const [progress, setProgress] = useState(0);
  const [uploadStatus, setUploadStatus] = useState('');
  const [saveError, setSaveError] = useState('');

  useResponsiveSignaturePad(clienteRef, clientePadContainerRef, clienteDrawingRef);
  useResponsiveSignaturePad(recepcionRef, recepcionPadContainerRef, recepcionDrawingRef);

  const { data, dataUpdatedAt, isFetching, isLoading, error, refetch } = useQuery({
    queryKey: ['ots', 'detail', routeId, 'firmas'],
    queryFn: () => refreshOtDetail(routeId),
    enabled: !!routeId,
    refetchInterval: OT_DETAIL_REFRESH_INTERVAL_MS,
    refetchOnReconnect: true,
    refetchOnWindowFocus: true,
  });

  const ot = data?.ot;
  const canMutate = canMutateOtRemotely(ot);
  const locked = isOtLocked(ot);

  useEffect(() => {
    setNombreCliente((current) => current || ot?.firma?.nombreFirmaCliente || '');
    setNombreRecepcion((current) => current || ot?.firma?.nombreFirmaRecepcion || '');
  }, [ot?.firma?.nombreFirmaCliente, ot?.firma?.nombreFirmaRecepcion]);

  const refreshData = async () => {
    await queryClient.invalidateQueries({ queryKey: ['ots', 'detail', routeId] });
    await queryClient.invalidateQueries({ queryKey: ['ots', 'detail', routeId, 'firmas'] });
    await queryClient.invalidateQueries({ queryKey: ['historial'] });
  };

  const saveMutation = useMutation({
    mutationFn: async () => {
      if (!ot?.serverId) {
        throw new Error('Primero guarda la OT para usar esta acción.');
      }

      const hasNewClienteFirma = Boolean(usaFirmaCliente && clienteRef.current && !clienteRef.current.isEmpty());
      const hasNewRecepcionFirma = Boolean(usaFirmaRecepcion && recepcionRef.current && !recepcionRef.current.isEmpty());
      const hasExistingFirma = Boolean(
        (usaFirmaCliente && ot.firma?.firmaCliente) || (usaFirmaRecepcion && ot.firma?.firmaRecepcion),
      );

      if (!hasNewClienteFirma && !hasNewRecepcionFirma && !hasExistingFirma) {
        throw new Error('Dibuja al menos una firma antes de guardar.');
      }

      if (hasNewClienteFirma && !nombreCliente.trim()) {
        throw new Error('Escribe el nombre de quien firma como cliente.');
      }

      if (hasNewRecepcionFirma && !nombreRecepcion.trim()) {
        throw new Error('Escribe el nombre de quien firma por recepción.');
      }

      setProgress(5);
      setSaveError('');
      setUploadStatus('Preparando firmas...');
      const payload: Record<string, any> = {
        nombreFirmaCliente: usaFirmaCliente ? nombreCliente.trim() || undefined : undefined,
        nombreFirmaRecepcion: usaFirmaRecepcion ? nombreRecepcion.trim() || undefined : undefined,
      };

      if (hasNewClienteFirma) {
        setUploadStatus('Preparando firma del cliente...');
        const file = await getSignatureUploadFile(clienteRef, `firma-cliente-${Date.now()}`);
        const uploaded = await uploadFileWithProgress(file, 'firma', (value) => setProgress(Math.max(10, Math.round(value * 0.45))), {
          onStatusChange: (status) => setUploadStatus(`Cliente: ${status.message}`),
        });
        payload.firmaCliente = uploaded.url;
      }

      if (hasNewRecepcionFirma) {
        setUploadStatus('Preparando firma de recepción...');
        const file = await getSignatureUploadFile(recepcionRef, `firma-recepcion-${Date.now()}`);
        const uploaded = await uploadFileWithProgress(file, 'firma', (value) => setProgress(Math.max(55, 50 + Math.round(value * 0.45))), {
          onStatusChange: (status) => setUploadStatus(`Recepcion: ${status.message}`),
        });
        payload.firmaRecepcion = uploaded.url;
      }

      setProgress(100);
      setUploadStatus('Guardando firmas en la OT...');
      return otsApi.saveFirmas(Number(ot.serverId), payload);
    },
    onSuccess: async (savedFirma: any) => {
      setUploadStatus('Firmas actualizadas correctamente.');
      setSaveError('');
      const mergedFirma = { ...(ot?.firma || {}), ...(savedFirma || {}) };
      if (ot?.serverId) {
        const existing = await db.ordenesTrabajo.where('serverId').equals(Number(ot.serverId)).first();
        if (existing) {
          await db.ordenesTrabajo.update(existing.localId, {
            firma: mergedFirma,
            lastModified: Date.now(),
          });
        }
      }
      clienteRef.current?.clear();
      recepcionRef.current?.clear();
      await refreshData();
      toast({ variant: 'success', title: 'Firmas guardadas', description: 'La OT ya tiene evidencia de cliente y recepción.' });
    },
    onError: (error: any) => {
      const message = error.message || 'No se pudieron guardar las firmas';
      setProgress(0);
      setUploadStatus('');
      setSaveError(message);
      toast({ variant: 'destructive', title: 'Error al guardar firmas', description: message });
    },
  });

  const handleSaveFirmas = () => {
    if (saveMutation.isPending) return;

    if (!ot?.serverId) {
      const message = 'La OT todavia no esta sincronizada con el servidor. Actualiza o espera a que termine la sincronizacion.';
      setSaveError(message);
      toast({ variant: 'destructive', title: 'No se puede guardar', description: message });
      return;
    }

    if (locked) {
      const message = 'La OT ya fue entregada y las firmas estan en modo consulta.';
      setSaveError(message);
      toast({ variant: 'destructive', title: 'No se puede guardar', description: message });
      return;
    }

    if (!navigator.onLine) {
      const message = 'No hay conexion. Conectate a internet para subir las firmas.';
      setSaveError(message);
      toast({ variant: 'destructive', title: 'Sin conexion', description: message });
      return;
    }

    saveMutation.mutate();
  };

  if (isLoading) {
    return (
      <div className="min-h-full pb-16 md:pb-10">
        <main className="mx-auto flex max-w-7xl flex-col gap-6">
          <Card className="overflow-hidden">
            <CardContent className="space-y-5 p-5 md:p-6">
              <SkeletonDetailHeader />
            </CardContent>
          </Card>
          <div className="grid gap-6 xl:grid-cols-2">
            <Skeleton className="h-96 w-full" />
            <Skeleton className="h-96 w-full" />
          </div>
        </main>
      </div>
    );
  }

  if (error || !ot) {
    return (
      <div className="flex min-h-[60dvh] items-center justify-center p-4">
        <ErrorState
          title={error ? 'No se pudo cargar la OT' : 'OT no encontrada'}
          description={error ? 'No logramos comunicarnos con el servidor. Revisa la conexión e intenta de nuevo.' : 'No fue posible abrir las firmas de esta OT.'}
          onRetry={() => (error ? refetch() : router.push('/dashboard/ots'))}
          retryLabel={error ? 'Reintentar' : 'Volver al listado'}
        />
      </div>
    );
  }

  return (
    <div className="min-h-full pb-16 md:pb-10">
      <main className="mx-auto flex max-w-7xl flex-col gap-6">
        <Card className="overflow-hidden">
          <CardContent className="space-y-5 p-5 md:p-6">
            <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
              <div className="flex items-start gap-3 md:gap-4">
                <Button variant="outline" size="icon" aria-label="Volver a la OT" onClick={() => router.push(`/dashboard/ots/${routeId}`)}>
                  <ArrowLeft className="h-4 w-4" />
                </Button>
                <div>
                  <div className="flex flex-wrap items-center gap-2">
                    <h1 className="text-2xl font-bold tracking-tight text-foreground">Firmas</h1>
                    <Badge variant="success">{ot.numeroOt}</Badge>
                    <Badge variant="neutral">{getEstadoLabel(ot.estado)}</Badge>
                  </div>
                  <p className="mt-2 text-sm text-muted-foreground">{ot.vehiculo?.placa || 'Sin placa'} | {formatDate(ot.fechaEntrada)}</p>
                  {locked ? <p className="mt-1 text-sm font-medium text-success">La OT ya fue entregada y las firmas quedaron en modo consulta.</p> : null}
                </div>
              </div>
              <DataRefreshControl updatedAt={dataUpdatedAt} isFetching={isFetching} onRefresh={() => void refetch()} />
            </div>
          </CardContent>
        </Card>

        <div className="grid gap-6 xl:grid-cols-2">
          {usaFirmaCliente ? (
            <DashboardSection title="Firma del cliente" description="El cliente puede firmar directo sobre la tablet. Usa borrar, deshacer o rehacer sin salir de la vista.">
              <div className="space-y-4">
                <Field label="Nombre de quien firma" htmlFor="firma-nombre-cliente">
                  <Input value={nombreCliente} onChange={(event) => setNombreCliente(event.target.value)} disabled={locked} />
                </Field>
                <div ref={clientePadContainerRef} className={`signature-pad h-52 touch-none overflow-hidden sm:h-64 md:h-72 ${locked ? 'pointer-events-none opacity-75' : ''}`}>
                  <SignatureCanvas
                    ref={clienteRef}
                    penColor="#0f172a"
                    onBegin={() => { clienteDrawingRef.current = true; }}
                    onEnd={() => { clienteDrawingRef.current = false; setSaveError(''); }}
                    canvasProps={{ className: 'h-full w-full rounded-3xl', style: { touchAction: 'none' } }}
                  />
                </div>
                <div className="flex flex-wrap gap-2">
                  <Button variant="outline" onClick={() => undoPad(clienteRef)} disabled={!canMutate}><RotateCcw className="mr-2 h-4 w-4" />Deshacer</Button>
                  <Button variant="outline" onClick={() => clearPad(clienteRef, setClienteBackup)} disabled={!canMutate}><Eraser className="mr-2 h-4 w-4" />Borrar</Button>
                  <Button variant="outline" onClick={() => restorePad(clienteRef, clienteBackup)} disabled={!canMutate || !clienteBackup.length}><RotateCcw className="mr-2 h-4 w-4" />Rehacer</Button>
                </div>

                {ot.firma?.firmaCliente ? (
                  <div className="rounded-xl border border-border bg-muted p-4">
                    <p className="text-sm font-semibold text-foreground">Firma actual</p>
                    <img src={normalizePrintAssetUrl(ot.firma.firmaCliente)} alt="Firma cliente" className="mt-3 h-36 w-full rounded-lg object-contain bg-surface" />
                    <p className="mt-2 text-sm text-muted-foreground">{ot.firma.nombreFirmaCliente || 'Sin nombre'}{ot.firma.fechaFirmaCliente ? ` | ${formatDateTime(ot.firma.fechaFirmaCliente)}` : ''}</p>
                  </div>
                ) : null}
              </div>
            </DashboardSection>
          ) : null}

          {usaFirmaRecepcion ? (
            <DashboardSection title="Firma de recepción" description="Confirma la entrega física de la unidad y deja evidencia de recepción.">
              <div className="space-y-4">
                <Field label="Nombre de quien recibe" htmlFor="firma-nombre-recepcion">
                  <Input value={nombreRecepcion} onChange={(event) => setNombreRecepcion(event.target.value)} disabled={locked} />
                </Field>
                <div ref={recepcionPadContainerRef} className={`signature-pad h-52 touch-none overflow-hidden sm:h-64 md:h-72 ${locked ? 'pointer-events-none opacity-75' : ''}`}>
                  <SignatureCanvas
                    ref={recepcionRef}
                    penColor="#0f172a"
                    onBegin={() => { recepcionDrawingRef.current = true; }}
                    onEnd={() => { recepcionDrawingRef.current = false; setSaveError(''); }}
                    canvasProps={{ className: 'h-full w-full rounded-3xl', style: { touchAction: 'none' } }}
                  />
                </div>
                <div className="flex flex-wrap gap-2">
                  <Button variant="outline" onClick={() => undoPad(recepcionRef)} disabled={!canMutate}><RotateCcw className="mr-2 h-4 w-4" />Deshacer</Button>
                  <Button variant="outline" onClick={() => clearPad(recepcionRef, setRecepcionBackup)} disabled={!canMutate}><Eraser className="mr-2 h-4 w-4" />Borrar</Button>
                  <Button variant="outline" onClick={() => restorePad(recepcionRef, recepcionBackup)} disabled={!canMutate || !recepcionBackup.length}><RotateCcw className="mr-2 h-4 w-4" />Rehacer</Button>
                </div>

                {ot.firma?.firmaRecepcion ? (
                  <div className="rounded-xl border border-border bg-muted p-4">
                    <p className="text-sm font-semibold text-foreground">Firma actual</p>
                    <img src={normalizePrintAssetUrl(ot.firma.firmaRecepcion)} alt="Firma recepción" className="mt-3 h-36 w-full rounded-lg object-contain bg-surface" />
                    <p className="mt-2 text-sm text-muted-foreground">{ot.firma.nombreFirmaRecepcion || 'Sin nombre'}{ot.firma.fechaFirmaRecepcion ? ` | ${formatDateTime(ot.firma.fechaFirmaRecepcion)}` : ''}</p>
                  </div>
                ) : null}
              </div>
            </DashboardSection>
          ) : null}
        </div>

        <DashboardSection title="Guardar firmas" description="Si ya existian firmas, solo se reemplazan las que vuelvas a dibujar.">
          <div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
            <div className="text-sm text-muted-foreground">Las firmas se suben como imagen optimizada y quedan ligadas a la OT para historial y cierre.</div>
            <Button disabled={saveMutation.isPending} onClick={handleSaveFirmas}>
              {saveMutation.isPending ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Save className="mr-2 h-4 w-4" />}
              {canMutate ? 'Guardar firmas' : 'Revisar firmas'}
            </Button>
          </div>
          {saveError ? (
            <div className="mt-4 rounded-xl border border-destructive/20 bg-destructive-soft px-4 py-3 text-sm font-medium text-destructive">{saveError}</div>
          ) : null}
          {saveMutation.isPending ? (
            <div className="mt-4">
              <div className="flex items-center justify-between text-sm text-muted-foreground"><span>Subiendo firmas</span><span>{progress}%</span></div>
              <div className="mt-2 h-2 overflow-hidden rounded-full bg-border"><div className="h-full rounded-full bg-primary transition-[width] duration-150 ease-out" style={{ width: `${progress}%` }} /></div>
              {uploadStatus ? <p className="mt-2 text-sm text-success">{uploadStatus}</p> : null}
            </div>
          ) : uploadStatus ? (
            <div className="mt-4 rounded-xl border border-success/30 bg-success-soft px-4 py-3 text-sm text-success">{uploadStatus}</div>
          ) : null}
        </DashboardSection>
      </main>
    </div>
  );
}
