import React, { useState, useRef, useEffect, useCallback } from 'react';
import { Map } from '../ui/map';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card';
import { Button } from '../ui/button';
import { Badge } from '../ui/badge';
import { Separator } from '../ui/separator';
import {
  MousePointer2,
  MapPin,
  Circle,
  Square,
  Hexagon,
  Trash2,
  Save,
  Undo,
  Check,
  X,
} from 'lucide-react';
import { toast } from 'sonner';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '../ui/dialog';
import { ScrollArea } from '../ui/scroll-area';

// Tipos para os modos de desenho
type DrawingMode = 'marker' | 'circle' | 'rectangle' | 'polygon' | null;

// Tipo para objetos desenhados
type DrawnShape = {
  type: DrawingMode;
  overlay:
    | google.maps.marker.AdvancedMarkerElement
    | google.maps.Circle
    | google.maps.Rectangle
    | google.maps.Polygon;
  data?: any;
};

export interface DrawingMapExampleProps {
  apiKey?: string;
}

export function DrawingMapExample({ apiKey }: DrawingMapExampleProps) {
  const [mapInstance, setMapInstance] = useState<google.maps.Map | null>(null);
  const [selectedMode, setSelectedMode] = useState<DrawingMode>(null);
  const [shapes, setShapes] = useState<DrawnShape[]>([]);
  const [showSaveDialog, setShowSaveDialog] = useState(false);
  const [savedData, setSavedData] = useState('');

  // Estado para desenho de polígono em andamento
  const [isDrawingPolygon, setIsDrawingPolygon] = useState(false);
  const tempPolylineRef = useRef<google.maps.Polyline | null>(null);
  const polygonPathRef = useRef<google.maps.LatLng[]>([]);

  // Refs para listeners do mapa para limpeza adequada
  const mapListenersRef = useRef<google.maps.MapsEventListener[]>([]);

  // Cores do Design System (Xertica Primary)
  const colors = {
    fill: '#2C275B', // Primary do CSS
    stroke: '#2C275B',
    fillOpacity: 0.2,
    strokeWeight: 2,
    editable: true,
    draggable: true,
  };

  // --- Funções de Desenho (definidas com useCallback para dependências) ---

  const addMarker = useCallback(
    (position: google.maps.LatLng) => {
      if (!mapInstance) return;

      // Utilizando AdvancedMarkerElement conforme recomendação (Marker depreciado)
      const marker = new google.maps.marker.AdvancedMarkerElement({
        position,
        map: mapInstance,
        gmpDraggable: true, // Propriedade correta para AdvancedMarkerElement
        title: 'Marcador',
      });

      marker.addListener('dragend', () => {
        toast.info('Posição do marcador atualizada');
      });

      const newShape: DrawnShape = { type: 'marker', overlay: marker };
      setShapes(prev => [...prev, newShape]);
      toast.success('Marcador adicionado');
    },
    [mapInstance]
  );

  const addCircle = useCallback(
    (center: google.maps.LatLng) => {
      if (!mapInstance) return;

      const circle = new google.maps.Circle({
        map: mapInstance,
        center: center,
        radius: 500,
        fillColor: colors.fill,
        fillOpacity: colors.fillOpacity,
        strokeColor: colors.stroke,
        strokeWeight: colors.strokeWeight,
        editable: true,
        draggable: true,
      });

      const newShape: DrawnShape = { type: 'circle', overlay: circle };
      setShapes(prev => [...prev, newShape]);
      toast.success('Círculo adicionado');
    },
    [mapInstance, colors]
  );

  const addRectangle = useCallback(
    (center: google.maps.LatLng) => {
      if (!mapInstance) return;

      const offset = 0.005;
      const bounds = {
        north: center.lat() + offset,
        south: center.lat() - offset,
        east: center.lng() + offset,
        west: center.lng() - offset,
      };

      const rectangle = new google.maps.Rectangle({
        map: mapInstance,
        bounds: bounds,
        fillColor: colors.fill,
        fillOpacity: colors.fillOpacity,
        strokeColor: colors.stroke,
        strokeWeight: colors.strokeWeight,
        editable: true,
        draggable: true,
      });

      const newShape: DrawnShape = { type: 'rectangle', overlay: rectangle };
      setShapes(prev => [...prev, newShape]);
      toast.success('Retângulo adicionado');
    },
    [mapInstance, colors]
  );

  const cancelPolygonDrawing = useCallback(() => {
    if (tempPolylineRef.current) {
      tempPolylineRef.current.setMap(null);
      tempPolylineRef.current = null;
    }
    polygonPathRef.current = [];
    setIsDrawingPolygon(false);
  }, []);

  const finishPolygon = useCallback(() => {
    if (!mapInstance || polygonPathRef.current.length < 3) {
      if (polygonPathRef.current.length < 3 && polygonPathRef.current.length > 0) {
        toast.error('Polígono precisa de pelo menos 3 pontos.');
      }
      return;
    }

    const polygon = new google.maps.Polygon({
      map: mapInstance,
      paths: polygonPathRef.current,
      fillColor: colors.fill,
      fillOpacity: colors.fillOpacity,
      strokeColor: colors.stroke,
      strokeWeight: colors.strokeWeight,
      editable: true,
      draggable: true,
    });

    const newShape: DrawnShape = { type: 'polygon', overlay: polygon };
    setShapes(prev => [...prev, newShape]);

    cancelPolygonDrawing();
    toast.success('Polígono criado com sucesso!');
  }, [mapInstance, colors, cancelPolygonDrawing]);

  const addPolygonPoint = useCallback(
    (point: google.maps.LatLng) => {
      if (!mapInstance) return;

      if (!isDrawingPolygon) {
        setIsDrawingPolygon(true);
        polygonPathRef.current = [point];

        tempPolylineRef.current = new google.maps.Polyline({
          map: mapInstance,
          path: polygonPathRef.current,
          strokeColor: colors.stroke,
          strokeOpacity: 0.8,
          strokeWeight: 2,
          geodesic: true,
          clickable: false, // Importante: não capturar cliques para não atrapalhar o mapa
        });

        toast.info('Clique para adicionar pontos. Duplo clique ou botão check para fechar.', {
          duration: 4000,
        });
      } else {
        polygonPathRef.current.push(point);
        tempPolylineRef.current?.setPath(polygonPathRef.current);
      }
    },
    [mapInstance, isDrawingPolygon, colors]
  );

  // --- Setup dos Listeners ---

  // Limpar listeners antigos
  const clearListeners = () => {
    mapListenersRef.current.forEach(listener => google.maps.event.removeListener(listener));
    mapListenersRef.current = [];
  };

  useEffect(() => {
    if (!mapInstance) return;

    clearListeners();

    if (!selectedMode) {
      mapInstance.setOptions({ draggableCursor: 'grab', clickableIcons: true });
      return;
    }

    mapInstance.setOptions({
      draggableCursor: 'crosshair',
      clickableIcons: false,
    });

    const clickListener = mapInstance.addListener('click', (e: google.maps.MapMouseEvent) => {
      if (!e.latLng) return;

      switch (selectedMode) {
        case 'marker':
          addMarker(e.latLng);
          break;
        case 'circle':
          addCircle(e.latLng);
          break;
        case 'rectangle':
          addRectangle(e.latLng);
          break;
        case 'polygon':
          addPolygonPoint(e.latLng);
          break;
      }
    });

    mapListenersRef.current.push(clickListener);

    // Listener especial para fechar polígono com duplo clique
    if (selectedMode === 'polygon') {
      const dblClickListener = mapInstance.addListener('dblclick', (e: any) => {
        if (e.domEvent) e.domEvent.stopPropagation();
        finishPolygon();
      });
      mapListenersRef.current.push(dblClickListener);
    }

    return () => {
      clearListeners();
    };
  }, [
    mapInstance,
    selectedMode,
    addMarker,
    addCircle,
    addRectangle,
    addPolygonPoint,
    finishPolygon,
  ]);

  // --- Ações Gerais ---

  const handleModeChange = (mode: DrawingMode) => {
    if (isDrawingPolygon) {
      cancelPolygonDrawing();
    }
    setSelectedMode(mode);
  };

  const clearAll = () => {
    shapes.forEach(shape => {
      if ('setMap' in shape.overlay) (shape.overlay as any).setMap(null);
      else (shape.overlay as any).map = null;
    });
    setShapes([]);
    if (isDrawingPolygon) cancelPolygonDrawing();
    toast.info('Mapa limpo');
  };

  const undoLast = () => {
    if (isDrawingPolygon) {
      if (polygonPathRef.current.length > 0) {
        polygonPathRef.current.pop();
        tempPolylineRef.current?.setPath(polygonPathRef.current);
        if (polygonPathRef.current.length === 0) {
          cancelPolygonDrawing();
        }
      }
      return;
    }

    if (shapes.length === 0) return;

    const lastShape = shapes[shapes.length - 1];
    if ('setMap' in lastShape.overlay) (lastShape.overlay as any).setMap(null);
    else (lastShape.overlay as any).map = null;
    setShapes(prev => prev.slice(0, prev.length - 1));
  };

  const handleSave = () => {
    if (shapes.length === 0) {
      toast.error('Adicione desenhos ao mapa antes de salvar.');
      return;
    }

    const exportData = shapes.map(s => {
      let data: any = {};

      if (s.type === 'marker') {
        const marker = s.overlay as google.maps.marker.AdvancedMarkerElement;
        const pos = marker.position;
        // Tratamento seguro para lat/lng que pode ser LatLng object ou LatLngLiteral
        if (pos) {
          const lat =
            typeof (pos as any).lat === 'function' ? (pos as any).lat() : (pos as any).lat;
          const lng =
            typeof (pos as any).lng === 'function' ? (pos as any).lng() : (pos as any).lng;
          data = { lat, lng };
        }
      } else if (s.type === 'circle') {
        const circle = s.overlay as google.maps.Circle;
        data = {
          center: { lat: circle.getCenter()?.lat(), lng: circle.getCenter()?.lng() },
          radius: circle.getRadius(),
        };
      } else if (s.type === 'rectangle') {
        const rect = s.overlay as google.maps.Rectangle;
        const bounds = rect.getBounds();
        data = {
          north: bounds?.getNorthEast().lat(),
          south: bounds?.getSouthWest().lat(),
          east: bounds?.getNorthEast().lng(),
          west: bounds?.getSouthWest().lng(),
        };
      } else if (s.type === 'polygon') {
        const poly = s.overlay as google.maps.Polygon;
        const path = poly.getPath();
        data = path.getArray().map(coord => ({ lat: coord.lat(), lng: coord.lng() }));
      }

      return { type: s.type, data };
    });

    setSavedData(JSON.stringify(exportData, null, 2));
    setShowSaveDialog(true);
  };

  // Botão auxiliar para renderizar itens da toolbar
  const ToolButton = ({
    active,
    onClick,
    icon: Icon,
    label,
  }: {
    active?: boolean;
    onClick: () => void;
    icon: any;
    label: string;
  }) => (
    <Button
      variant={active ? 'default' : 'ghost'}
      className={`w-full justify-start gap-3 ${active ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:text-foreground'}`}
      onClick={onClick}
    >
      <Icon className="h-4 w-4" />
      <span className="text-sm font-medium">{label}</span>
    </Button>
  );

  return (
    <Card className="h-full border-0 shadow-none md:border md:shadow-sm">
      <CardHeader className="border-b bg-muted/20 pb-4">
        <div className="flex items-center justify-between">
          <div>
            <CardTitle>Ferramentas de Desenho</CardTitle>
            <CardDescription className="mt-1">
              Crie geometrias personalizadas no mapa
            </CardDescription>
          </div>
          <Badge variant="outline" className="h-6">
            {shapes.length} {shapes.length === 1 ? 'elemento' : 'elementos'}
          </Badge>
        </div>
      </CardHeader>

      <CardContent className="p-0 flex flex-col md:flex-row h-[600px] bg-background">
        {/* Sidebar de Ferramentas */}
        <div className="w-full md:w-64 border-b md:border-b-0 md:border-r bg-muted/10 flex flex-col">
          <ScrollArea className="flex-1">
            <div className="p-4 space-y-6">
              {/* Seção Modos */}
              <div className="space-y-3">
                <h4 className="text-xs font-semibold text-muted-foreground uppercase tracking-wider px-2">
                  Ferramentas
                </h4>
                <div className="space-y-1">
                  <ToolButton
                    active={selectedMode === null}
                    onClick={() => handleModeChange(null)}
                    icon={MousePointer2}
                    label="Navegar"
                  />
                  <ToolButton
                    active={selectedMode === 'marker'}
                    onClick={() => handleModeChange('marker')}
                    icon={MapPin}
                    label="Marcador"
                  />
                  <ToolButton
                    active={selectedMode === 'circle'}
                    onClick={() => handleModeChange('circle')}
                    icon={Circle}
                    label="Círculo"
                  />
                  <ToolButton
                    active={selectedMode === 'rectangle'}
                    onClick={() => handleModeChange('rectangle')}
                    icon={Square}
                    label="Retângulo"
                  />
                  <ToolButton
                    active={selectedMode === 'polygon'}
                    onClick={() => handleModeChange('polygon')}
                    icon={Hexagon}
                    label="Polígono"
                  />
                </div>
              </div>

              <Separator />

              {/* Seção Ações */}
              <div className="space-y-3">
                <h4 className="text-xs font-semibold text-muted-foreground uppercase tracking-wider px-2">
                  Ações
                </h4>
                <div className="grid grid-cols-2 gap-2">
                  <Button
                    variant="outline"
                    onClick={undoLast}
                    disabled={shapes.length === 0 && !isDrawingPolygon}
                    className="w-full"
                    title="Desfazer último"
                    aria-label="Desfazer último"
                  >
                    <Undo className="h-4 w-4 mr-2" />
                    Desfazer
                  </Button>
                  <Button
                    variant="destructive"
                    onClick={clearAll}
                    disabled={shapes.length === 0 && !isDrawingPolygon}
                    className="w-full bg-destructive/10 text-destructive hover:bg-destructive hover:text-destructive-foreground border-0 shadow-none"
                  >
                    <Trash2 className="h-4 w-4 mr-2" />
                    Limpar
                  </Button>
                </div>

                <Button
                  variant="default"
                  onClick={handleSave}
                  disabled={shapes.length === 0}
                  className="w-full mt-2"
                >
                  <Save className="h-4 w-4 mr-2" />
                  Salvar GeoJSON
                </Button>
              </div>
            </div>
          </ScrollArea>

          {/* Status do Polígono (Floating Action na Sidebar em mobile, ou fixo embaixo em desktop) */}
          {isDrawingPolygon && (
            <div className="p-4 bg-primary/5 border-t border-primary/10">
              <div className="flex items-center gap-2 mb-2 text-primary text-xs font-medium">
                <span className="relative flex h-2 w-2">
                  <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
                  <span className="relative inline-flex rounded-full h-2 w-2 bg-primary"></span>
                </span>
                Desenhando Polígono...
              </div>
              <div className="flex gap-2">
                <Button
                  size="sm"
                  className="w-full bg-green-600 hover:bg-green-700 text-white"
                  onClick={finishPolygon}
                >
                  <Check className="h-3 w-3 mr-1" /> Concluir
                </Button>
                <Button
                  size="sm"
                  variant="outline"
                  className="w-full"
                  onClick={cancelPolygonDrawing}
                >
                  <X className="h-3 w-3 mr-1" /> Cancelar
                </Button>
              </div>
            </div>
          )}
        </div>

        {/* Área do Mapa */}
        <div className="flex-1 relative bg-muted/5 min-h-[400px]">
          <Map
            className="h-full w-full rounded-none md:rounded-br-lg"
            center={{ lat: -23.5505, lng: -46.6333 }}
            zoom={13}
            height="100%"
            mapContainerClassName="h-full w-full rounded-none md:rounded-br-lg"
            disableDefaultUI={true}
            zoomControl={true}
            onMapLoad={setMapInstance}
            apiKey={apiKey}
          />

          {/* Instruções Flutuantes */}
          {selectedMode && !isDrawingPolygon && (
            <div className="absolute bottom-6 left-1/2 -translate-x-1/2 bg-background/90 backdrop-blur border px-4 py-2 rounded-full shadow-sm text-xs font-medium text-muted-foreground pointer-events-none z-10">
              {selectedMode === 'marker' && 'Clique no mapa para adicionar um marcador'}
              {selectedMode === 'circle' && 'Clique no mapa para definir o centro do círculo'}
              {selectedMode === 'rectangle' && 'Clique no mapa para criar um retângulo'}
              {selectedMode === 'polygon' && 'Clique sequencialmente para desenhar a área'}
            </div>
          )}
        </div>

        {/* Dialog de Salvamento */}
        <Dialog open={showSaveDialog} onOpenChange={setShowSaveDialog}>
          <DialogContent className="max-w-md">
            <DialogHeader>
              <DialogTitle>Dados Geográficos (GeoJSON)</DialogTitle>
              <DialogDescription>Copie os dados das formas desenhadas abaixo.</DialogDescription>
            </DialogHeader>
            <div className="relative mt-2">
              <pre className="p-4 rounded-lg bg-muted overflow-auto max-h-[300px] text-xs font-mono scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent">
                {savedData}
              </pre>
            </div>
            <div className="flex justify-end mt-4">
              <Button onClick={() => setShowSaveDialog(false)}>Fechar</Button>
            </div>
          </DialogContent>
        </Dialog>
      </CardContent>
    </Card>
  );
}
