import { Icono } from '@gustito/shared/iconos';
import FacturaFiscal from '../components/FacturaFiscal';
import { useEffect, useRef, useState } from 'react';
import { useParams, Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import {
  ESTADO_META,
  formatUsd,
  enlaceWhatsApp,
  variablesTema,
  type SeguimientoPedido,
  type EstadoPedido,
} from '@gustito/shared';
import { supabase } from '../lib/supabase';
import SeccionPago from './SeccionPago';

const MAP_STYLE = {
  version: 8 as const,
  sources: {
    osm: {
      type: 'raster' as const,
      tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
      tileSize: 256,
      attribution: '© OpenStreetMap',
    },
  },
  layers: [{ id: 'osm', type: 'raster' as const, source: 'osm' }],
};

const PASOS_DELIVERY: EstadoPedido[] = [
  'recibido',
  'confirmado',
  'preparando',
  'listo',
  'en_camino',
  'entregado',
];
const PASOS_PICKUP: EstadoPedido[] = ['recibido', 'confirmado', 'preparando', 'listo', 'entregado'];

// Hora aproximada de "listo" = confirmado + minutos estimados.
function horaAprox(confirmadoEn: string, min: number): string {
  const t = new Date(new Date(confirmadoEn).getTime() + min * 60000);
  return `${String(t.getHours()).padStart(2, '0')}:${String(t.getMinutes()).padStart(2, '0')}`;
}

export default function Seguimiento() {
  const { id = '' } = useParams();

  const { data, isLoading, error } = useQuery({
    queryKey: ['seguimiento', id],
    queryFn: async () => {
      const { data, error } = await supabase.rpc('pedido_seguimiento', { p_pedido_id: id });
      if (error) throw error;
      const fila = (data as unknown as SeguimientoPedido[])?.[0];
      if (!fila) throw new Error('No encontramos este pedido.');
      return fila;
    },
    // Un pedido entregado o cancelado ya no cambia mas: seguir preguntando cada
    // 8 segundos por cada cliente que dejo la pantalla abierta es carga regalada.
    refetchInterval: (q) => {
      const e = (q.state.data as SeguimientoPedido | undefined)?.estado;
      return e === 'entregado' || e === 'cancelado' ? false : 8000;
    },
  });

  // El cliente NO abre conexiones de Realtime, a proposito.
  //
  // Antes cada persona que dejaba abierta la pantalla de su pedido ocupaba una
  // conexion, y ese cupo es el MISMO que usan las pantallas del negocio (panel,
  // cocina, mesas). Con muchos locales a la vez, los clientes terminaban
  // sacando del aire a los restaurantes, que es lo que de verdad no puede
  // fallar. La posicion del motorizado ya viene en `pedido_seguimiento`
  // (el repartidor la guarda cada 15 segundos), asi que el mapa se pinta con el
  // mismo sondeo que trae el estado: misma informacion, cero conexiones.

  if (isLoading) return <Centrado>Cargando pedido...</Centrado>;
  if (error || !data) return <Centrado>{(error as Error)?.message ?? 'Error'}</Centrado>;

  const cancelado = data.estado === 'cancelado';
  const pasos = data.tipo_entrega === 'delivery' ? PASOS_DELIVERY : PASOS_PICKUP;
  const idxActual = pasos.indexOf(data.estado);

  const destino =
    data.direccion_latitud != null && data.direccion_longitud != null
      ? { lat: data.direccion_latitud, lng: data.direccion_longitud }
      : null;
  const repartidor =
    data.repartidor_latitud != null && data.repartidor_longitud != null
      ? { lat: data.repartidor_latitud, lng: data.repartidor_longitud }
      : null;

  return (
    <div
      className="min-h-full max-w-xl mx-auto p-4"
      style={variablesTema(data.restaurante_color) as React.CSSProperties}
    >
      <header className="bg-marca text-marca-contraste rounded-2xl p-5">
        <p className="text-white/80 text-sm">{data.restaurante_nombre}</p>
        <h1 className="text-2xl font-bold">Pedido {data.codigo}</h1>
        <p className="mt-1 text-sm">Total: {formatUsd(data.total_usd)}</p>
      </header>

      <Link
        to={`/ticket/${id}`}
        className="mt-3 block text-center text-sm font-bold text-marca-oscuro"
      >
        Ver mi ticket con QR
      </Link>
      <FacturaFiscal tipo="pedido" id={id} />

      {cancelado ? (
        <div className="mt-4 bg-red-50 text-red-700 rounded-xl p-4 font-medium">
          Este pedido fue cancelado.
        </div>
      ) : (
        <>
          {data.tipo_entrega === 'reserva' &&
            (data.cuenta_id ? (
              <Link
                to={`/cuenta/${data.cuenta_id}`}
                className="mt-4 flex items-center justify-between gap-3 rounded-2xl border-2 border-marca bg-marca-claro p-4"
              >
                <div>
                  <p className="font-bold text-marca-oscuro">Ya tienes mesa asignada</p>
                  <p className="text-sm text-marca-oscuro">Mesa {data.mesa} · toca para ver tu cuenta y pedir algo más</p>
                </div>
                <span className="text-marca-oscuro text-2xl leading-none">›</span>
              </Link>
            ) : (
              <div className="mt-4 flex items-center gap-3 rounded-xl bg-marca-claro p-3 text-marca-oscuro">
                <Icono nombre="reloj" className="h-6 w-6 text-marca-oscuro shrink-0" />
                <p className="text-sm font-bold">
                  Reserva para {data.personas ?? 1} persona{(data.personas ?? 1) === 1 ? '' : 's'}. Al llegar, muestra
                  tu ticket con QR al mesero para que te asigne mesa.
                </p>
              </div>
            ))}

          <div className="mt-4">
            <SeccionPago pedidoId={id} />
          </div>

          <div
            className="mt-4 rounded-xl p-4 text-white font-semibold text-center"
            style={{ backgroundColor: ESTADO_META[data.estado].color }}
          >
            {ESTADO_META[data.estado].label}
          </div>

          {/* Despedida al cerrar el pedido. Aqui se deja de preguntar por el
              estado (ya no cambia mas), asi que este es el ultimo mensaje que
              ve el cliente: que no se quede con el cartel verde a secas. */}
          {data.estado === 'entregado' && (
            <p className="mt-3 rounded-xl bg-marca-claro p-3 text-center text-sm font-bold text-marca-oscuro">
              {data.tipo_entrega === 'delivery'
                ? '¡Buen provecho y gracias por tu compra!'
                : '¡Buen provecho y gracias por tu visita!'}
            </p>
          )}

          {data.tiempo_estimado_min != null &&
            !['listo', 'en_camino', 'entregado', 'cancelado'].includes(data.estado) && (
              <div className="mt-3 flex items-center gap-3 rounded-xl bg-marca-claro p-3 text-marca-oscuro">
                <Icono nombre="reloj" className="h-6 w-6 text-marca-oscuro" />
                <div>
                  <p className="text-sm font-bold">
                    Tu pedido estara listo en ~{data.tiempo_estimado_min} min
                  </p>
                  {data.confirmado_en && (
                    <p className="text-xs">
                      Aprox. a las {horaAprox(data.confirmado_en, data.tiempo_estimado_min)}
                    </p>
                  )}
                </div>
              </div>
            )}

          {/* Linea de tiempo */}
          <ol className="mt-4 space-y-2">
            {pasos.map((paso, i) => {
              const hecho = i <= idxActual;
              return (
                <li key={paso} className="flex items-center gap-3">
                  <span
                    className={`w-3 h-3 rounded-full ${hecho ? '' : 'bg-gray-300'}`}
                    style={hecho ? { backgroundColor: ESTADO_META[paso].color } : undefined}
                  />
                  <span className={`text-sm ${hecho ? 'text-gray-800 font-medium' : 'text-gray-400'}`}>
                    {ESTADO_META[paso].label}
                  </span>
                </li>
              );
            })}
          </ol>

          {data.tipo_entrega === 'delivery' && (repartidor || destino) && (
            <div className="mt-4">
              <p className="text-sm font-medium text-gray-700 mb-2">
                {repartidor ? 'Tu repartidor en camino' : 'Direccion de entrega'}
              </p>
              <Mapa destino={destino} repartidor={repartidor} />
            </div>
          )}
        </>
      )}

      {data.restaurante_telefono && (
        <div className="mt-4 grid grid-cols-2 gap-2">
          {(() => {
            const wa = enlaceWhatsApp(
              data.restaurante_telefono,
              `Hola ${data.restaurante_nombre}, soy cliente del pedido ${data.codigo}.`,
            );
            return wa ? (
              <a
                href={wa}
                target="_blank"
                rel="noopener noreferrer"
                className="flex items-center justify-center gap-2 rounded-xl bg-[#25D366] py-3 font-semibold text-white"
              >
                <IconoWhatsApp /> WhatsApp
              </a>
            ) : (
              <span />
            );
          })()}
          <a
            href={`tel:${data.restaurante_telefono}`}
            className="flex items-center justify-center rounded-xl border border-marca py-3 font-semibold text-marca-oscuro"
          >
            Llamar
          </a>
        </div>
      )}
    </div>
  );
}

function IconoWhatsApp({ className = 'h-5 w-5' }: { className?: string }) {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" className={className} aria-hidden>
      <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51l-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.71.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.548 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z" />
    </svg>
  );
}

function Mapa({
  destino,
  repartidor,
}: {
  destino: { lat: number; lng: number } | null;
  repartidor: { lat: number; lng: number } | null;
}) {
  const ref = useRef<HTMLDivElement | null>(null);
  const mapRef = useRef<maplibregl.Map | null>(null);
  const repMarker = useRef<maplibregl.Marker | null>(null);
  const destMarker = useRef<maplibregl.Marker | null>(null);

  useEffect(() => {
    if (!ref.current || mapRef.current) return;
    const center = repartidor ?? destino ?? { lat: 9.5597, lng: -69.2019 };
    const map = new maplibregl.Map({
      container: ref.current,
      style: MAP_STYLE as maplibregl.StyleSpecification,
      center: [center.lng, center.lat],
      zoom: 14,
    });
    mapRef.current = map;
    return () => {
      map.remove();
      mapRef.current = null;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    const map = mapRef.current;
    if (!map) return;
    if (destino) {
      if (!destMarker.current) destMarker.current = new maplibregl.Marker({ color: '#16A34A' });
      destMarker.current.setLngLat([destino.lng, destino.lat]).addTo(map);
    }
    if (repartidor) {
      if (!repMarker.current) repMarker.current = new maplibregl.Marker({ color: '#F97316' });
      repMarker.current.setLngLat([repartidor.lng, repartidor.lat]).addTo(map);
      map.easeTo({ center: [repartidor.lng, repartidor.lat], duration: 800 });
    }
  }, [destino, repartidor]);

  return <div ref={ref} className="w-full h-64 rounded-xl overflow-hidden border" />;
}

function Centrado({ children }: { children: React.ReactNode }) {
  return (
    <div className="min-h-full flex items-center justify-center p-6 text-center text-gray-600">
      {children}
    </div>
  );
}
