import { Component, Input, OnInit, OnDestroy, ChangeDetectorRef, OnChanges, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { Subject, Observable, of, from, forkJoin } from 'rxjs';
import { takeUntil, map, catchError, share, concatMap, delay, scan, takeLast } from 'rxjs/operators';
import { GeocodingService } from '../../services/geocoding/geocoding.service';
import { VehiclesService } from '../../../domain/vehicles/vehicles.service';
import { DriversService } from '../../../domain/drivers/drivers.service';
import { PersonService } from '../../services/person.service';
import { environment } from '../../../../environments/environment';
import { Driver } from '../../../domain/drivers/driver.interface';

// 🚚 Interface para dados do veículo (do backend)
export interface VehicleData {
  id: string;
  license_plate?: string;
  model?: string;
  last_latitude: number | null;
  last_longitude: number | null;
  last_address_cep?: string | null;
  last_address_city?: string | null;
  last_address_uf?: string | null;
  last_address_street?: string | null;
  last_address_number?: string | null;
  last_address_complement?: string | null;
  last_address_neighborhood?: string | null;
  last_location_timestamp?: string | null;
  driverId?: string | null;
  location_person_id?: string | null;
}

// 🚚 Interface para dados processados do rastreamento
export interface ProcessedLocationData {
  hasLocation: boolean;
  latitude: number;
  longitude: number;
  timestamp: Date | null;
  formattedAddress: string;
  addressComponents: {
    street?: string;
    number?: string;
    complement?: string;
    neighborhood?: string;
    city?: string;
    state?: string;
    cep?: string;
  };
}

// 📍 Interface para dados de localização da API
export interface VehicleLocationApiResponse {
  lat: number;
  lon: number;
  speed: number;
  fuel: number;
  odometer: number;
  engine_hours: number;
  address_uf: string | null;
  address_city: string | null;
  address_street: string | null;
  address_country: string | null;
  address_reference: string | null;
  ignition_status: string;
  gps_signal_status: string;
  satellite_origin: string;
  is_vehicle_blocked: boolean;
  id: number;
  vehicleId: number;
  timestamp: string;
  createdAt: string;
  updatedAt: string;
}

// 📍 Interface para histórico de localizações
export interface LocationHistoryItem {
  id: string;
  address: string;
  city: string;
  state: string;
  latitude: number;
  longitude: number;
  timestamp: Date;
  status: 'em-movimento' | 'estacionado' | 'parado';
  duration?: string; // Tempo que ficou no local
  speed: number; // Velocidade em km/h
  timeBetween?: {
    duration: string;        // "15min 30s"
    durationMs: number;      // em millisegundos
    distanceTraveled?: number; // em metros
    averageSpeed?: number;   // km/h calculado entre pontos
    isStationary?: boolean;  // true se foi parado/estacionado
  };
}

// 🎯 Interface para agrupamento de localizações
export interface LocationCluster {
  representativePoint: VehicleLocationApiResponse;
  clusteredPoints: VehicleLocationApiResponse[];
  startTime: Date;
  endTime: Date;
  duration: number; // em minutos
  status: 'em-movimento' | 'estacionado' | 'parado';
  averagePosition: { lat: number; lon: number };
  totalDistance: number; // distância total percorrida no cluster
}

@Component({
  selector: 'app-vehicle-location-tracker',
  standalone: true,
  imports: [CommonModule],
  template: `
    <div class="vehicle-location-tracker">
      <!-- 📍 Estado de Loading -->
      <div class="loading-state" *ngIf="isLoadingVehicleData">
        <div class="loading-icon">
          <i class="fas fa-spinner fa-spin"></i>
        </div>
        <div class="loading-content">
          <h4>Carregando dados do veículo...</h4>
          <p>Aguarde enquanto buscamos as informações de localização.</p>
        </div>
      </div>

      <!-- 📍 Estado de Erro -->
      <div class="error-state" *ngIf="error && !isLoadingVehicleData">
        <div class="error-icon">
          <i class="fas fa-exclamation-triangle"></i>
        </div>
        <div class="error-content">
          <h4>Erro ao carregar localização</h4>
          <p>{{ error }}</p>
          <button class="retry-btn" (click)="retryLoadData()">
            <i class="fas fa-refresh"></i>
            Tentar novamente
          </button>
        </div>
      </div>

      <!-- 📍 Estado sem Localização -->
      <div class="no-location-state" *ngIf="!isLoadingVehicleData && !error && (!processedLocation || !processedLocation.hasLocation)">
        <div class="no-location-icon">
          <i class="fas fa-map-marker-alt"></i>
        </div>
        <div class="no-location-content">
          <h4>Localização não disponível</h4>
          <p>Este veículo não possui dados de localização GPS ou as coordenadas não são válidas.</p>
          <div class="vehicle-info" *ngIf="vehicleData">
            <strong>Veículo:</strong> {{ vehicleData.license_plate || 'N/A' }} - {{ vehicleData.model || 'N/A' }}
          </div>
        </div>
      </div>

      <!-- 📍 Informações de Localização (Estilo fiel à imagem) -->
      <div class="location-info-card" *ngIf="!isLoadingVehicleData && !error && processedLocation?.hasLocation">
        <div class="info-header">
          <h3>
            <i class="fas fa-map-marker-alt"></i>
            Informações de Localização
          </h3>
          <div class="update-status" [class.updating]="isLoadingAddress">
            <i class="fas fa-check-circle"></i>
            {{ isLoadingAddress ? 'Carregando endereço...' : 'Endereço carregado' }}
            <button class="map-btn" (click)="refreshGeocodedAddress()" [disabled]="isLoadingAddress">
              <i class="fas fa-refresh" [class.fa-spin]="isLoadingAddress"></i>
              {{ isLoadingAddress ? 'Carregando...' : 'Atualizar Endereço' }}
            </button>
          </div>
        </div>

        <div class="location-grid">
          <!-- Primeira linha: 4 colunas -->
          <div class="location-item" *ngIf="false">
            <i class="fas fa-clock"></i>
            <div class="item-content">
              <label>Última Atualização</label>
              <span>{{ getFormattedTimestamp() }}</span>
            </div>
          </div>

          <div class="location-item" *ngIf="false">
            <i class="fas fa-city"></i>
            <div class="item-content">
              <label>Cidade Atual</label>
              <span>{{ getCurrentCity() }}</span>
            </div>
          </div>

            <!-- Segunda linha: Endereço completo full-widt-->
            <div class="location-item">
            <i class="fas fa-map-marker"></i>
            <div class="item-content">
              <label>Endereço Atual</label>
              <span>{{ getCurrentAddress() }}</span>
            </div>
          </div>


                     <div class="location-item" 
                [class.clickable]="driverHomeLocation"
                [class.near-home]="isNearDriverHome()"
                (click)="onDriverHomeClick()"
                [title]="driverHomeLocation ? 'Clique para ver no mapa: ' + driverAddress : 'Carregando endereço...'">
             <i class="fas fa-home" [class.near-home-icon]="isNearDriverHome()"></i>
             <div class="item-content">
               <label>
                 Endereço do motorista
                 <span class="proximity-indicator" *ngIf="isNearDriverHome()">
                   <i class="fas fa-map-marker-alt"></i>
                   Próximo ({{ getDistanceToDriverHome() }})
                 </span>
               </label>
               <span>{{ getAddressDriver() }}</span>
             </div>
             <div class="home-action" *ngIf="driverHomeLocation">
               <i class="fas fa-map-marker-alt"></i>
             </div>
           </div>

          <!-- 🏢 Local de Operação -->
          <div class="location-item" 
               [class.clickable]="operationLocation"
               [class.near-operation]="isNearOperationLocation()"
               (click)="onOperationLocationClick()"
               [title]="operationLocation ? 'Clique para ver no mapa: ' + operationLocationAddress : 'Carregando endereço...'">
            <i class="fas fa-building" [class.near-operation-icon]="isNearOperationLocation()"></i>
            <div class="item-content">
              <label>
                Local de Operação
                <span class="proximity-indicator" *ngIf="isNearOperationLocation()">
                  <i class="fas fa-map-marker-alt"></i>
                  Próximo ({{ getDistanceToOperationLocation() }})
                </span>
              </label>
              <span>{{ getOperationLocationAddress() }}</span>
            </div>
            <div class="operation-action" *ngIf="operationLocation">
              <i class="fas fa-map-marker-alt"></i>
            </div>
          </div>

<!-- 
          <div class="location-item">
            <i class="fas fa-signal"></i>
            <div class="item-content">
              <label>Status</label>
              <span class="status-badge" [class]="getMovementStatusClass()">{{ getMovementStatus() }}</span>
            </div>
          </div> -->

        

          <!-- Terceira linha: Signal e Status -->
          <!-- <div class="location-item half-width">
            <i class="fas fa-wifi"></i>
            <div class="item-content">
              <label>Sinal</label>
              <span class="signal-badge strong">Forte</span>
            </div>
          </div>

          <div class="location-item half-width">
            <i class="fas fa-exclamation-triangle"></i>
            <div class="item-content">
              <label>Status</label>
              <span class="alert-badge active">Ativo</span>
            </div>
          </div> -->
        </div>
      </div>

      <!-- 🗺️ Mapa de Localização -->
      <div class="map-container" *ngIf="!isLoadingVehicleData && !error && processedLocation?.hasLocation">
        <div class="map-header">
          <h4>
            <i class="fas fa-map"></i>
            Localização Atual
          </h4>
          <!-- <div class="map-controls">
            <button class="map-btn" (click)="centerMap()">
              <i class="fas fa-crosshairs"></i>
              Centralizar
            </button>
            <button class="map-btn" (click)="refreshGeocodedAddress()" [disabled]="isLoadingAddress">
              <i class="fas fa-refresh" [class.fa-spin]="isLoadingAddress"></i>
              {{ isLoadingAddress ? 'Carregando...' : 'Atualizar Endereço' }}
            </button>
          </div> -->
        </div>

        <div class="map-wrapper">
          <!-- Google Maps Embed -->
          <iframe
            [src]="getMapEmbedUrl()"
            class="google-map"
            frameborder="0"
            allowfullscreen
            loading="lazy"
            referrerpolicy="no-referrer-when-downgrade">
          </iframe>
          
          <!-- Overlay com informações -->
          <div class="map-overlay">
            <div class="coordinates-info">
              <span>{{ processedLocation?.latitude?.toFixed(6) }}, {{ processedLocation?.longitude?.toFixed(6) }}</span>
            </div>
          </div>
        </div>
      </div>

      <!-- 📜 Informações Detalhadas do Endereço -->
      <div class="address-details-card" *ngIf="!isLoadingVehicleData && !error && processedLocation?.hasLocation && hasDetailedAddress()">
        <div class="details-header">
          <h4>
            <i class="fas fa-info-circle"></i>
            Detalhes do Endereço
          </h4>
        </div>

        <div class="address-grid">
          <div class="address-item" *ngIf="processedLocation?.addressComponents?.street">
            <label>Logradouro:</label>
            <span>{{ processedLocation?.addressComponents?.street }}</span>
          </div>
          <div class="address-item" *ngIf="processedLocation?.addressComponents?.number">
            <label>Número:</label>
            <span>{{ processedLocation?.addressComponents?.number }}</span>
          </div>
          <div class="address-item" *ngIf="processedLocation?.addressComponents?.complement">
            <label>Complemento:</label>
            <span>{{ processedLocation?.addressComponents?.complement }}</span>
          </div>
          <div class="address-item" *ngIf="processedLocation?.addressComponents?.neighborhood">
            <label>Bairro:</label>
            <span>{{ processedLocation?.addressComponents?.neighborhood }}</span>
          </div>
          <div class="address-item" *ngIf="processedLocation?.addressComponents?.city">
            <label>Cidade:</label>
            <span>{{ processedLocation?.addressComponents?.city }}</span>
          </div>
          <div class="address-item" *ngIf="processedLocation?.addressComponents?.state">
            <label>Estado:</label>
            <span>{{ processedLocation?.addressComponents?.state }}</span>
          </div>
          <div class="address-item" *ngIf="processedLocation?.addressComponents?.cep">
            <label>CEP:</label>
            <span>{{ processedLocation?.addressComponents?.cep }}</span>
          </div>
        </div>
      </div>

      <!-- 🏃 Estatísticas de Velocidade e Paradas -->
      <div class="speed-stats-card" *ngIf="locationHistory.length > 0 && speedStats.totalReadings > 0">
        <div class="stats-header">
          <h4>
            <i class="fas fa-tachometer-alt"></i>
            Estatísticas de Velocidade
          </h4>
          <div class="stats-count">
            {{ speedStats.totalReadings }} leituras
          </div>
        </div>

        <div class="stats-grid">
          <div class="stat-item highlight-max clickable" 
               (click)="onMaxSpeedClick()"
               [title]="'Clique para ver no mapa onde ocorreu a velocidade máxima (' + speedStats.maxSpeed + ' km/h)'">
            <div class="stat-icon">
              <i class="fas fa-rocket"></i>
            </div>
            <div class="stat-content">
              <div class="stat-label">Velocidade Máxima</div>
              <div class="stat-value">{{ speedStats.maxSpeed }} <span class="stat-unit">km/h</span></div>
              <div class="stat-hint">
                <i class="fas fa-map-marker-alt"></i>
                Clique para ver no mapa
              </div>
            </div>
          </div>
          
          <div class="stat-item highlight-frequent">
            <div class="stat-icon">
              <i class="fas fa-chart-bar"></i>
            </div>
            <div class="stat-content">
              <div class="stat-label">Mais Frequente</div>
              <div class="stat-value">{{ speedStats.mostFrequentSpeed }} <span class="stat-unit">km/h</span></div>
            </div>
          </div>
          
          <div class="stat-item">
            <div class="stat-icon">
              <i class="fas fa-calculator"></i>
            </div>
            <div class="stat-content">
              <div class="stat-label">Velocidade Média</div>
              <div class="stat-value">{{ speedStats.averageSpeed }} <span class="stat-unit">km/h</span></div>
            </div>
          </div>
        </div>
      </div>

      <!-- 🛑 Estatísticas de Paradas e Estacionamentos -->
      <div class="stop-stats-card" *ngIf="locationHistory.length > 0 && (stopStats.totalStops > 0 || stopStats.totalParked > 0)">
        <div class="stats-header">
          <h4>
            <i class="fas fa-pause-circle"></i>
            Estatísticas de Paradas
          </h4>
          <div class="stats-count">
            {{ stopStats.totalStops + stopStats.totalParked }} eventos
          </div>
        </div>

        <div class="stats-grid">
          <div class="stat-item highlight-stops">
            <div class="stat-icon">
              <i class="fas fa-hand-paper"></i>
            </div>
            <div class="stat-content">
              <div class="stat-label">Paradas</div>
              <div class="stat-value">{{ stopStats.totalStops }} <span class="stat-unit">vezes</span></div>
              <div class="stat-detail" *ngIf="stopStats.formattedStopTime !== '0min'">
                <i class="fas fa-clock"></i>
                {{ stopStats.formattedStopTime }} total
              </div>
            </div>
          </div>
          
          <div class="stat-item highlight-parked">
            <div class="stat-icon">
              <i class="fas fa-parking"></i>
            </div>
            <div class="stat-content">
              <div class="stat-label">Estacionamentos</div>
              <div class="stat-value">{{ stopStats.totalParked }} <span class="stat-unit">vezes</span></div>
              <div class="stat-detail" *ngIf="stopStats.formattedParkedTime !== '0min'">
                <i class="fas fa-clock"></i>
                {{ stopStats.formattedParkedTime }} total
              </div>
            </div>
          </div>
          
          <div class="stat-item">
            <div class="stat-icon">
              <i class="fas fa-stopwatch"></i>
            </div>
            <div class="stat-content">
              <div class="stat-label">Tempo Total Parado</div>
              <div class="stat-value">{{ formatMinutesToDuration(stopStats.totalStopTime + stopStats.totalParkedTime) }}</div>
              <div class="stat-detail">
                <i class="fas fa-info-circle"></i>
                Paradas + Estacionamentos
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 📍 Histórico de Localizações -->
      <div class="location-history-card" *ngIf="locationHistory.length > 0">
        <div class="history-header">
          <div class="header-left">
            <h4>
              <i class="fas fa-history"></i>
              Histórico de Localizações
            </h4>
            <div class="header-stats">
              <span class="stat-item">
                <i class="fas fa-list"></i>
                {{ locationHistory.length }} registros
              </span>
              <span class="stat-item" *ngIf="selectedMarkers.length > 0">
                <i class="fas fa-map-marker-alt"></i>
                {{ selectedMarkers.length }} no mapa
              </span>
            </div>
          </div>
          
          <div class="header-right">
            <button 
              class="clear-markers-btn" 
              type="button"
              *ngIf="selectedMarkers.length > 0"
              (click)="clearMapMarkers()"
              title="Limpar {{ selectedMarkers.length }} marcador(es) do mapa">
              <i class="fas fa-times"></i>
              Limpar Mapa
            </button>
          </div>
        </div>

        <div class="history-list">
          <ng-container *ngFor="let item of locationHistory; let i = index">
            
            <!-- 📍 Item do histórico -->
            <div 
              class="history-item" 
              [class.latest]="i === 0"
              [class.selected]="isLocationSelected(item)"
              (click)="onLocationItemClick(item)"
              [title]="isLocationSelected(item) ? 'Clique para remover do mapa: ' + item.address : 'Clique para adicionar no mapa: ' + item.address">
              
              <div class="history-icon">
                <i class="fas fa-map-marker-alt" [class]="getStatusClass(item.status)"></i>
                <!-- 🎯 Número do marcador se selecionado -->
                <span class="marker-number" *ngIf="isLocationSelected(item)">
                  {{ getMarkerNumber(item) }}
                </span>
              </div>

              <div class="history-content">
                <div class="history-address">
                  <strong>{{ item.address }}</strong>
                  <span class="history-city">{{ item.city }}, {{ item.state }}</span>
                </div>
                
                <div class="history-meta">
                  <div class="history-date">
                    <i class="fas fa-clock"></i>
                    {{ formatHistoryDate(item.timestamp) }}
                  </div>
                  
                  <div class="history-speed">
                    <i class="fas fa-tachometer-alt"></i>
                    {{ item.speed }} km/h
                  </div>
                  
                  <div class="history-duration" *ngIf="item.duration">
                    <i class="fas fa-hourglass-half"></i>
                    {{ item.duration }}
                  </div>
                </div>
              </div>

              <div class="history-status">
                <span class="status-badge" [class]="getStatusClass(item.status)">
                  {{ getStatusText(item.status) }}
                </span>
                <!-- 🎯 Indicador de remoção para itens selecionados -->
                <div class="remove-indicator" *ngIf="isLocationSelected(item)" title="Clique para remover do mapa">
                  <i class="fas fa-times"></i>
                </div>
              </div>
            </div>

            <!-- ⏱️ Tempo entre pontos (aparece entre os registros) -->
            <div class="time-between-indicator" *ngIf="item.timeBetween && i < locationHistory.length - 1">
              <div class="time-content">
                <span class="time-duration">
                  <i class="fas fa-clock"></i>
                  {{ item.timeBetween.duration }}
                </span>
                
                <span class="time-separator">•</span>
                
                <span class="time-distance" *ngIf="item.timeBetween.distanceTraveled && item.timeBetween.distanceTraveled > 0">
                  <i class="fas fa-route"></i>
                  {{ formatDistance(item.timeBetween.distanceTraveled) }}
                </span>
                
                <span class="time-separator" *ngIf="item.timeBetween.averageSpeed && item.timeBetween.averageSpeed > 0">•</span>
                
                <span class="time-speed" 
                      *ngIf="item.timeBetween.averageSpeed && item.timeBetween.averageSpeed > 0"
                      [class.high-speed]="item.timeBetween.averageSpeed > 80">
                  <i class="fas fa-tachometer-alt"></i>
                  {{ item.timeBetween.averageSpeed }} km/h média
                  <i class="fas fa-bolt" *ngIf="item.timeBetween.averageSpeed > 80"></i>
                </span>
                
                <span class="time-stationary" *ngIf="item.timeBetween.isStationary">
                  <i class="fas fa-pause-circle"></i>
                  {{ item.status === 'parado' ? 'Parado' : 'Estacionado' }}
                </span>
              </div>
            </div>

          </ng-container>
        </div>

        <div class="history-footer">
          <button 
            class="history-load-more" 
            type="button"
            (click)="loadMoreHistory()"
            [disabled]="isLoadingMore || !hasMoreData"
            [class.loading]="isLoadingMore">
            <i class="fas" [class.fa-chevron-down]="!isLoadingMore" [class.fa-spinner]="isLoadingMore" [class.fa-spin]="isLoadingMore"></i>
            <span *ngIf="!isLoadingMore && hasMoreData">Carregar mais registros</span>
            <span *ngIf="isLoadingMore">Carregando...</span>
            <span *ngIf="!hasMoreData && !isLoadingMore">Todos os registros carregados</span>
          </button>
        </div>
      </div>
    </div>
  `,
  styleUrl: './vehicle-location-tracker.component.scss'
})
export class VehicleLocationTrackerComponent implements OnInit, OnDestroy, OnChanges {
  @Input() vehicleData: VehicleData | undefined;

  @Input() set initialData(data: VehicleData) {
    if (data) {
      // alert('Dados recebidos via initialData: '+data);
      console.log('🎯 [VEHICLE-LOCATION] Dados recebidos via initialData:', data);
      this.vehicleData = data;
      this.processVehicleData();
    }
  }

  processedLocation: ProcessedLocationData | null = null;
  currentGeocodedAddress: string = '';
  isLoadingAddress: boolean = false;
  error: string | null = null;
  locationHistory: LocationHistoryItem[] = [];
  isLoadingVehicleData: boolean = false;
  isLoadingHistory: boolean = false;
  historyError: string | null = null;

  private destroy$ = new Subject<void>();

  // 🎯 Cache e otimização de geocoding
  private geocodingCache = new Map<string, string>();
  private pendingGeocodingRequests = new Map<string, Observable<string>>();
  private readonly CACHE_GRID_SIZE = 500; // metros para agrupamento de cache
  private readonly BATCH_SIZE = 5; // processar 5 endereços por vez
  private readonly RATE_LIMIT_DELAY = 150; // 150ms entre chamadas

  // 📄 Controle de paginação
  currentPage = 1;
  hasMoreData = true;
  isLoadingMore = false;
  readonly PAGE_SIZE = 30; // itens por página

  // 🗺️ Controle de marcadores no mapa
  selectedMarkers: Array<{
    id: string;
    lat: number;
    lon: number;
    address: string;
    timestamp: Date;
    markerIndex: number;
  }> = [];
  private markerCounter = 0;

  // 🏃 Estatísticas de velocidade
  speedStats = {
    maxSpeed: 0,
    mostFrequentSpeed: 0,
    averageSpeed: 0,
    totalReadings: 0
  };

  // 🛑 Estatísticas de paradas e estacionamentos
  stopStats = {
    totalStops: 0,           // Quantidade de paradas
    totalParked: 0,          // Quantidade de estacionamentos
    totalStopTime: 0,        // Tempo total parado (em minutos)
    totalParkedTime: 0,      // Tempo total estacionado (em minutos)
    formattedStopTime: '',   // Tempo formatado (ex: "2h 30min")
    formattedParkedTime: ''  // Tempo formatado (ex: "1h 45min")
  };

  // 📍 Localização da velocidade máxima
  maxSpeedLocation: LocationHistoryItem | null = null;

  // 🏠 Dados do motorista e residência
  driverData: Driver | null = null;
  driverAddress: string = '';
  driverHomeLocation: { lat: number; lng: number } | null = null;
  isLoadingDriverData: boolean = false;

  // 🏢 Dados do local de operação
  operationLocationData: any | null = null;
  operationLocationAddress: string = '';
  operationLocation: { lat: number; lng: number } | null = null;
  isLoadingOperationLocationData: boolean = false;

  constructor(
    private geocodingService: GeocodingService,
    private vehicleService: VehiclesService,
    private driversService: DriversService,
    private personService: PersonService,
    private cdr: ChangeDetectorRef,
    private sanitizer: DomSanitizer
  ) {}

  ngOnInit() {

    console.log('🎯 [VEHICLE-LOCATION] Dados recebidos via initialData:', this.vehicleData);
    console.log('🎯 [VEHICLE-LOCATION] Dados GPS do rastreador:', this.vehicleData?.last_latitude, this.vehicleData?.last_longitude);
    // Só processar se já temos dados
    if (this.vehicleData) {
      this.processVehicleData();
    }
    
    // Carregar dados mockados do histórico 
    this.loadMockLocationHistory();
    
    // Carregar dados do motorista
    this.loadDriverData();

    // Carregar dados do local de operação
    this.loadOperationLocationData();

    // Carregar dos do endereço do veículo

  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes['vehicleData'] && !changes['vehicleData'].firstChange) {
      this.processVehicleData();
    }
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }

  /**
   * 🔄 Processar dados do veículo
   */
  processVehicleData() {
    this.error = null;
    this.isLoadingVehicleData = true;

    try {
      if (!this.vehicleData) {
        this.error = 'Dados do veículo não fornecidos';
        return;
      }

      // Verificar se tem coordenadas válidas
      const hasValidCoordinates = 
        this.vehicleData.last_latitude !== null && 
        this.vehicleData.last_longitude !== null &&
        !isNaN(this.vehicleData.last_latitude) &&
        !isNaN(this.vehicleData.last_longitude);

      if (!hasValidCoordinates) {
        this.processedLocation = {
          hasLocation: false,
          latitude: 0,
          longitude: 0,
          timestamp: null,
          formattedAddress: '',
          addressComponents: {}
        };
        return;
      }

      // Processar timestamp
      let timestamp: Date | null = null;
      if (this.vehicleData.last_location_timestamp) {
        timestamp = new Date(this.vehicleData.last_location_timestamp);
        if (isNaN(timestamp.getTime())) {
          timestamp = null;
        }
      }

      // Criar dados processados
      this.processedLocation = {
        hasLocation: true,
        latitude: this.vehicleData.last_latitude!,
        longitude: this.vehicleData.last_longitude!,
        timestamp: timestamp,
        formattedAddress: this.buildFormattedAddress(),
        addressComponents: {
          street: this.vehicleData.last_address_street || undefined,
          number: this.vehicleData.last_address_number || undefined,
          complement: this.vehicleData.last_address_complement || undefined,
          neighborhood: this.vehicleData.last_address_neighborhood || undefined,
          city: this.vehicleData.last_address_city || undefined,
          state: this.vehicleData.last_address_uf || undefined,
          cep: this.vehicleData.last_address_cep || undefined
        }
      };

      // Se não tem endereço, tentar geocodificar
      if (!this.processedLocation.formattedAddress.trim()) {
        this.refreshGeocodedAddress();
      }

    } catch (error: any) {
      console.error('❌ Erro ao processar dados do veículo:', error);
      this.error = error.message || 'Erro ao processar dados de localização';
    } finally {
      this.isLoadingVehicleData = false;
      this.cdr.detectChanges();
    }
  }

  /**
   * 📍 Construir endereço formatado a partir dos dados existentes
   */
  private buildFormattedAddress(): string {
    if (!this.vehicleData) return '';
    
    const parts: string[] = [];

    // Rua e número
    if (this.vehicleData.last_address_street) {
      let streetPart = this.vehicleData.last_address_street;
      if (this.vehicleData.last_address_number) {
        streetPart += `, ${this.vehicleData.last_address_number}`;
      }
      parts.push(streetPart);
    }

    // Complemento
    if (this.vehicleData.last_address_complement) {
      parts.push(this.vehicleData.last_address_complement);
    }

    // Bairro
    if (this.vehicleData.last_address_neighborhood) {
      parts.push(this.vehicleData.last_address_neighborhood);
    }

    // Cidade e Estado
    if (this.vehicleData.last_address_city) {
      let cityPart = this.vehicleData.last_address_city;
      if (this.vehicleData.last_address_uf) {
        cityPart += ` - ${this.vehicleData.last_address_uf}`;
      }
      parts.push(cityPart);
    }

    // CEP
    if (this.vehicleData.last_address_cep) {
      parts.push(`CEP: ${this.vehicleData.last_address_cep}`);
    }

    return parts.length > 0 ? parts.join(', ') : '';
  }

  /**
   * 🔄 Atualizar endereço via geocodificação
   */
  refreshGeocodedAddress() {
    if (!this.processedLocation?.hasLocation) return;

    this.isLoadingAddress = true;
    
    this.geocodingService.reverseGeocode(
      this.processedLocation.latitude, 
      this.processedLocation.longitude
    )
    .pipe(takeUntil(this.destroy$))
    .subscribe({
      next: (result) => {
        if (result) {
          this.currentGeocodedAddress = result.formattedAddress || result.address || '';
          
          // Se não tem endereço dos dados originais, usar o geocodificado
          if (this.processedLocation && !this.processedLocation.formattedAddress.trim()) {
            this.processedLocation.formattedAddress = this.currentGeocodedAddress;
          }
          
          this.cdr.detectChanges(); 
        }
        this.isLoadingAddress = false;
      },
      error: (error) => {
        console.error('❌ Erro na geocodificação:', error);
        this.isLoadingAddress = false;
        this.cdr.detectChanges();
      }
    });
  }

  /**
   * 🗺️ Gerar URL do Google Maps Embed (sanitizado)
   */
  getMapEmbedUrl(): SafeResourceUrl {
    // Se há marcadores selecionados, mostrar mapa com marcadores
    if (this.selectedMarkers.length > 0) {
      return this.getMapUrlWithMarkers();
    }

    // Caso contrário, mostrar localização atual do veículo
    if (!this.processedLocation?.hasLocation) {
      return this.sanitizer.bypassSecurityTrustResourceUrl('');
    }

    const { latitude, longitude } = this.processedLocation;
    const zoom = 15;
    
    // ✅ Usar API key do environment
    const apiKey = environment.googleMapsApiKey;
    
    const url = `https://www.google.com/maps/embed/v1/place?key=${apiKey}&q=${latitude},${longitude}&zoom=${zoom}&maptype=roadmap`;
    
    return this.sanitizer.bypassSecurityTrustResourceUrl(url);
  }

  /**
   * 🗺️ Gerar URL do mapa com marcadores múltiplos
   */
  private getMapUrlWithMarkers(): SafeResourceUrl {
    if (this.selectedMarkers.length === 0) {
      return this.sanitizer.bypassSecurityTrustResourceUrl('');
    }

    // Se há apenas um marcador, usar place simples
    if (this.selectedMarkers.length === 1) {
      const marker = this.selectedMarkers[0];
      const mapUrl = `https://www.google.com/maps/embed/v1/place?key=${environment.googleMapsApiKey}&q=${marker.lat},${marker.lon}&zoom=15`;
      return this.sanitizer.bypassSecurityTrustResourceUrl(mapUrl);
    }
    
    // Para múltiplos marcadores, usar a API de Directions
    const firstMarker = this.selectedMarkers[0];
    const lastMarker = this.selectedMarkers[this.selectedMarkers.length - 1];
    
    let mapUrl = `https://www.google.com/maps/embed/v1/directions?key=${environment.googleMapsApiKey}`;
    mapUrl += `&origin=${firstMarker.lat},${firstMarker.lon}`;
    mapUrl += `&destination=${lastMarker.lat},${lastMarker.lon}`;
    
    // Adicionar waypoints (pontos intermediários) se houver mais de 2 marcadores
    if (this.selectedMarkers.length > 2) {
      const waypoints = this.selectedMarkers.slice(1, -1).map(marker => `${marker.lat},${marker.lon}`).join('|');
      mapUrl += `&waypoints=${waypoints}`;
    }
    
    mapUrl += `&zoom=13&maptype=roadmap`;

    return this.sanitizer.bypassSecurityTrustResourceUrl(mapUrl);
  }

  /**
   * 🎯 Centralizar mapa (placeholder)
   */
  centerMap() {
    console.log('🎯 Centralizando mapa...');
    // TODO: Implementar centralização se usando Google Maps Component
  }

  /**
   * 📅 Obter timestamp formatado
   */
  getFormattedTimestamp(): string {
    if (!this.processedLocation?.timestamp) {
      // Dados padrão até receber da API
      return '21/05/2024 - 09:45';
    }
    
    return new Intl.DateTimeFormat('pt-BR', {
      day: '2-digit',
      month: '2-digit',
      year: 'numeric',
      hour: '2-digit',
      minute: '2-digit'
    }).format(this.processedLocation.timestamp);
  }

  /**
   * 🏙️ Obter cidade atual
   */
  getCurrentCity(): string {
    const city = this.processedLocation?.addressComponents.city;
    const state = this.processedLocation?.addressComponents.state;
    
    if (city && state) {
      return `${city} - ${state}`;
    } else if (city) {
      return city;
    } else {
      // Dados padrão até receber da API
      return 'São Paulo - SP';
    }
  }

  /**
   * 📍 Obter endereço atual
   */
  getCurrentAddress(): string {
    if (this.processedLocation?.formattedAddress) {
      return this.processedLocation.formattedAddress;
    } else if (this.currentGeocodedAddress) {
      return this.currentGeocodedAddress;
    } else {
      // Dados padrão até receber da API
      return '';
    }
  }

  /**
   * 🛣️ Obter informações da rua
   */
  getStreetInfo(): string {
    const street = this.processedLocation?.addressComponents.street;
    const number = this.processedLocation?.addressComponents.number;
    
    if (street && number) {
      return `${street}, ${number}`;
    } else if (street) {
      return street;
    } else {
      return 'Rua não informada';
    }
  }

  /**
   * ✅ Verificar se tem componentes de endereço
   */
  hasAddressComponents(): boolean {
    if (!this.processedLocation?.addressComponents) return false;
    
    const components = this.processedLocation.addressComponents;
    return !!(components.street || components.neighborhood || components.city);
  }

  /**
   * 📋 Verificar se tem endereço detalhado
   */
  hasDetailedAddress(): boolean {
    if (!this.processedLocation?.addressComponents) return false;
    
    const components = this.processedLocation.addressComponents;
    return !!(
      components.street || 
      components.number || 
      components.complement || 
      components.neighborhood || 
      components.city || 
      components.state || 
      components.cep
    );
  }

  /**
   * 📍 Carregar dados otimizados do histórico de localizações
   */
  private loadMockLocationHistory(isLoadMore: boolean = false): void {
    if (isLoadMore) {
      this.isLoadingMore = true;
    } else {
      this.isLoadingHistory = true;
      this.currentPage = 1;
      this.locationHistory = []; // Limpar histórico apenas no carregamento inicial
    }
    
    this.historyError = null;

    // Buscar dados reais do histórico de localizações com agrupamento inteligente
    this.vehicleService.getVehicleLocationData(
      Number(this.vehicleData?.id), 
      this.currentPage, 
      this.PAGE_SIZE
    ).pipe(
      takeUntil(this.destroy$)
    ).subscribe({
      next: (response) => {
        console.log('🎯 [VEHICLE-LOCATION] Dados recebidos via getVehicleLocationData:', response);
        
        // Aplicar algoritmo de agrupamento para otimizar chamadas à API
        const clusters = this.clusterLocations(response.data);
        
        // Converter clusters em LocationHistoryItem (sem endereços ainda)
        const initialLocations = clusters.map((cluster: LocationCluster) => {
          const point = cluster.representativePoint;
          
          // Usar posição média para clusters com múltiplos pontos
          const lat = cluster.clusteredPoints.length > 1 ? cluster.averagePosition.lat : point.lat;
          const lon = cluster.clusteredPoints.length > 1 ? cluster.averagePosition.lon : point.lon;
          
          // Calcular velocidade média do cluster
          const avgSpeed = cluster.clusteredPoints.reduce((sum, p) => sum + p.speed, 0) / cluster.clusteredPoints.length;
          
          return {
            id: point.id.toString(),
            address: point.address_street || point.address_reference || 'Carregando endereço...',
            city: point.address_city || 'Carregando...',
            state: point.address_uf || 'Carregando...',
            latitude: lat,
            longitude: lon,
            timestamp: cluster.startTime,
            status: cluster.status,
            duration: cluster.duration > 0 ? this.formatDuration(cluster.duration * 60 * 1000) : undefined, // Converter minutos para ms
            speed: Math.round(avgSpeed) // Velocidade média do cluster
          };
        });

        // Concatenar ou definir histórico (dependendo se é carregamento inicial ou "carregar mais")
        if (isLoadMore) {
          this.locationHistory = [...this.locationHistory, ...initialLocations];
          this.isLoadingMore = false;
        } else {
          this.locationHistory = initialLocations;
          this.isLoadingHistory = false;
        }

        // Verificar se há mais dados para carregar
        this.hasMoreData = response.data.length === this.PAGE_SIZE && response.currentPage < response.pageCount;
        
        // ⏱️ Calcular tempo entre pontos
        this.locationHistory = this.calculateTimeBetweenPoints(this.locationHistory);
        
        // Calcular estatísticas de velocidade
        this.calculateSpeedStats();
        
        // Calcular estatísticas de paradas e estacionamentos
        this.calculateStopStats();
        
        this.cdr.detectChanges();

        console.log('🎯 [VEHICLE-LOCATION] Histórico atualizado:', this.locationHistory.length, 'pontos', 
                   '| Página:', this.currentPage, '| Tem mais dados:', this.hasMoreData);

        // Processar endereços em background com otimizações
        this.batchProcessAddresses(initialLocations).pipe(
          takeUntil(this.destroy$)
        ).subscribe({
          next: (locationsWithAddresses) => {
            console.log('🎯 [VEHICLE-LOCATION] Endereços processados com sucesso');
            
            // Atualizar apenas os novos itens processados
            if (isLoadMore) {
              // Substituir os últimos itens (que foram adicionados sem endereços) pelos processados
              const existingCount = this.locationHistory.length - initialLocations.length;
              this.locationHistory = [
                ...this.locationHistory.slice(0, existingCount),
                ...locationsWithAddresses
              ];
            } else {
              this.locationHistory = locationsWithAddresses;
            }
            
            this.cdr.detectChanges();
          },
          error: (error) => {
            console.error('🎯 [VEHICLE-LOCATION] Erro ao processar endereços:', error);
            // Manter histórico inicial mesmo com erro nos endereços
          }
        });
      },
      error: (error) => {
        console.error('🎯 [VEHICLE-LOCATION] Erro ao carregar dados:', error);
        this.historyError = 'Erro ao carregar histórico de localizações';
        
        if (isLoadMore) {
          this.isLoadingMore = false;
        } else {
          this.isLoadingHistory = false;
        }
        
        this.cdr.detectChanges();
      }
    });
    


    // this.locationHistory = [
    //   {
    //     id: '1',
    //     address: 'Av. Paulista, 1000',
    //     city: 'São Paulo',
    //     state: 'SP',
    //     latitude: -23.5647,
    //     longitude: -46.6527,
    //     timestamp: new Date('2024-05-21T09:45:00'),
    //     status: 'em-movimento'
    //   },
    //   {
    //     id: '2', 
    //     address: 'Rua Augusta, 500',
    //     city: 'São Paulo',
    //     state: 'SP',
    //     latitude: -23.5562,
    //     longitude: -46.6520,
    //     timestamp: new Date('2024-05-21T08:30:00'),
    //     status: 'estacionado',
    //     duration: '2h 15min'
    //   },
    //   {
    //     id: '3',
    //     address: 'Av. Rebouças, 3000',
    //     city: 'São Paulo', 
    //     state: 'SP',
    //     latitude: -23.5630,
    //     longitude: -46.6729,
    //     timestamp: new Date('2024-05-20T18:45:00'),
    //     status: 'em-movimento'
    //   },
    //   {
    //     id: '4',
    //     address: 'Rua Consolação, 1500',
    //     city: 'São Paulo',
    //     state: 'SP', 
    //     latitude: -23.5505,
    //     longitude: -46.6600,
    //     timestamp: new Date('2024-05-20T16:20:00'),
    //     status: 'parado',
    //     duration: '45min'
    //   },
    //   {
    //     id: '5',
    //     address: 'Av. Brasil, 2000',
    //     city: 'São Paulo',
    //     state: 'SP',
    //     latitude: -23.5329,
    //     longitude: -46.6395,
    //     timestamp: new Date('2024-05-20T14:10:00'),
    //     status: 'em-movimento'
    //   }
    // ];

    console.log('📍 Histórico de localizações carregado:', this.locationHistory);
  }

  /**
   * 🎨 Obter classe CSS para status do histórico
   */
  getStatusClass(status: string): string {
    switch (status) {
      case 'em-movimento':
        return 'status-moving';
      case 'estacionado':
        return 'status-parked';
      case 'parado':
        return 'status-stopped';
      default:
        return 'status-unknown';
    }
  }

  /**
   * 🎨 Obter texto do status do histórico
   */
  getStatusText(status: string): string {
    switch (status) {
      case 'em-movimento':
        return 'Em movimento';
      case 'estacionado':
        return 'Estacionado';
      case 'parado':
        return 'Parado';
      default:
        return 'Desconhecido';
    }
  }

  /**
   * 📅 Formatar data do histórico
   */
  formatHistoryDate(date: Date): string {
    return new Intl.DateTimeFormat('pt-BR', {
      day: '2-digit',
      month: '2-digit',
      year: 'numeric',
      hour: '2-digit',
      minute: '2-digit'
    }).format(date);
  }

  /**
   * 📡 Obter nome do rastreador (dados padrão até receber da API)
   */
  getTrackerName(): string {
    // Dados padrão até implementar API
    return 'T4S Rastreador Pro';
  }

  /**
   * 🚦 Obter status de movimento
   */
  getMovementStatus(): string {
    // Dados padrão até implementar API
    return 'Em movimento';
  }

  /**
   * 🎨 Obter classe CSS para status de movimento
   */
  getMovementStatusClass(): string {
    // Dados padrão até implementar API
    return 'status-moving';
  }

  retryLoadData() {
    this.processVehicleData();
  }

  /**
   * 📄 Carregar mais registros (paginação)
   */
  loadMoreHistory(): void {
    if (this.isLoadingMore || !this.hasMoreData) {
      return;
    }

    this.currentPage++;
    console.log('🎯 [PAGINATION] Carregando página:', this.currentPage);
    this.loadMockLocationHistory(true);
  }

  /**
   * 🗺️ Adicionar/remover marcador no mapa ao clicar em item da lista
   */
  onLocationItemClick(location: LocationHistoryItem): void {
    // Verificar se o item já está selecionado
    const existingMarkerIndex = this.selectedMarkers.findIndex(marker => marker.id === location.id);
    
    if (existingMarkerIndex !== -1) {
      // Item já selecionado - remover da seleção
      const removedMarker = this.selectedMarkers.splice(existingMarkerIndex, 1)[0];
      
      console.log('🎯 [MAP-MARKER] Removido marcador', removedMarker.markerIndex, ':', {
        address: location.address,
        coordinates: `${location.latitude}, ${location.longitude}`
      });
      
      // Reorganizar índices dos marcadores restantes
      this.reorganizeMarkerIndices();
    } else {
      // Item não selecionado - adicionar à seleção
      this.markerCounter++;
      
      const marker = {
        id: location.id,
        lat: location.latitude,
        lon: location.longitude,
        address: location.address,
        timestamp: location.timestamp,
        markerIndex: this.markerCounter
      };

      this.selectedMarkers.push(marker);
      
      console.log('🎯 [MAP-MARKER] Adicionado marcador', this.markerCounter, ':', {
        address: location.address,
        coordinates: `${location.latitude}, ${location.longitude}`
      });
    }

    // Atualizar URL do mapa com todos os marcadores
    this.updateMapWithMarkers();
  }

  /**
   * 🔄 Reorganizar índices dos marcadores após remoção
   */
  private reorganizeMarkerIndices(): void {
    // Reordenar marcadores por ordem de adição (timestamp ou índice original)
    this.selectedMarkers.sort((a, b) => a.markerIndex - b.markerIndex);
    
    // Reassignar índices sequenciais
    this.selectedMarkers.forEach((marker, index) => {
      marker.markerIndex = index + 1;
    });
    
    // Atualizar contador para o próximo marcador
    this.markerCounter = this.selectedMarkers.length;
    
    console.log('🎯 [MAP-MARKER] Índices reorganizados:', this.selectedMarkers.map(m => ({
      id: m.id,
      index: m.markerIndex,
      address: m.address.substring(0, 30) + '...'
    })));
  }

  /**
   * 🎯 Verificar se um item do histórico está selecionado no mapa
   */
  isLocationSelected(location: LocationHistoryItem): boolean {
    return this.selectedMarkers.some(marker => marker.id === location.id);
  }

  /**
   * 🎯 Obter o número do marcador para um item selecionado
   */
  getMarkerNumber(location: LocationHistoryItem): number | null {
    const marker = this.selectedMarkers.find(marker => marker.id === location.id);
    return marker ? marker.markerIndex : null;
  }

  /**
   * 🗺️ Atualizar mapa com todos os marcadores selecionados
   */
  private updateMapWithMarkers(): void {
    // O mapa será atualizado automaticamente via getMapEmbedUrl()
    this.cdr.detectChanges();
    console.log('🎯 [MAP-UPDATE] Mapa atualizado com', this.selectedMarkers.length, 'marcadores');
  }

  /**
   * 🎨 Obter cor do marcador baseado no índice
   */
  private getMarkerColor(index: number): string {
    const colors = ['red', 'blue', 'green', 'yellow', 'purple', 'orange', 'pink', 'gray'];
    return colors[index % colors.length];
  }

  /**
   * 🗑️ Limpar todos os marcadores do mapa
   */
  clearMapMarkers(): void {
    this.selectedMarkers = [];
    this.markerCounter = 0;
    
    // O mapa voltará automaticamente para a localização atual do veículo via getMapEmbedUrl()
    this.cdr.detectChanges();
    
    console.log('🎯 [MAP-CLEAR] Todos os marcadores foram removidos');
  }

  /**
   * ⏱️ Calcular tempo entre pontos consecutivos
   */
  private calculateTimeBetweenPoints(locations: LocationHistoryItem[]): LocationHistoryItem[] {
    if (locations.length < 2) return locations;

    const processedLocations = [...locations];

    for (let i = 0; i < processedLocations.length - 1; i++) {
      const currentPoint = processedLocations[i];
      const nextPoint = processedLocations[i + 1];

      const currentTime = new Date(currentPoint.timestamp).getTime();
      const nextTime = new Date(nextPoint.timestamp).getTime();
      const durationMs = currentTime - nextTime; // Diferença em ms (current é mais recente)

      if (durationMs > 0) {
        // Calcular distância entre pontos
        const distance = this.calculateDistance(
          currentPoint.latitude,
          currentPoint.longitude,
          nextPoint.latitude,
          nextPoint.longitude
        );

        // Verificar se é evento estacionário
        const isStationary = nextPoint.status === 'parado' || nextPoint.status === 'estacionado';

        // Calcular velocidade média (apenas se houve movimento significativo)
        let averageSpeed = 0;
        if (distance > 50 && durationMs > 0 && !isStationary) { // Mínimo 50m para calcular velocidade
          const durationHours = durationMs / (1000 * 60 * 60);
          const distanceKm = distance / 1000;
          averageSpeed = Math.round(distanceKm / durationHours);
        }

        // Adicionar informações de tempo entre pontos
        nextPoint.timeBetween = {
          duration: this.formatDuration(durationMs),
          durationMs: durationMs,
          distanceTraveled: Math.round(distance),
          averageSpeed: averageSpeed,
          isStationary: isStationary
        };
      }
    }

    return processedLocations;
  }

  /**
   * 🕐 Formatar duração em formato legível
   */
  private formatDuration(durationMs: number): string {
    const totalMinutes = Math.floor(durationMs / (1000 * 60));
    const hours = Math.floor(totalMinutes / 60);
    const minutes = totalMinutes % 60;
    const seconds = Math.floor((durationMs % (1000 * 60)) / 1000);

    if (hours > 0) {
      return `${hours}h ${minutes}min`;
    } else if (minutes > 0) {
      if (seconds > 0) {
        return `${minutes}min ${seconds}s`;
      }
      return `${minutes}min`;
    } else {
      return `${seconds}s`;
    }
  }

  /**
   * 📏 Formatar distância em formato legível
   */
  formatDistance(distanceMeters: number): string {
    if (distanceMeters >= 1000) {
      const km = (distanceMeters / 1000).toFixed(1);
      return `${km}km`;
    } else {
      return `${Math.round(distanceMeters)}m`;
    }
  }

  /**
   * 🏢 Carregar dados do local de operação
   */
  private loadOperationLocationData(): void {
    if (!this.vehicleData?.id) {
      console.warn('🏢 [OPERATION-LOCATION] ID do veículo não encontrado');
      return;
    }

    this.isLoadingOperationLocationData = true;
        
        if (this.vehicleData?.location_person_id) {
          console.log('🏢 [OPERATION-LOCATION] Location Person ID encontrado:', this.vehicleData.location_person_id);
          
          // Buscar dados da pessoa/local de operação usando PersonService
          this.personService.getById(this.vehicleData.location_person_id).pipe(
            takeUntil(this.destroy$)
          ).subscribe({
            next: async (personResponse) => {
              this.operationLocationData = personResponse.data;
              await this.processOperationLocationAddress();
              this.isLoadingOperationLocationData = false;
              this.cdr.detectChanges();
              
              console.log('🏢 [OPERATION-LOCATION] Dados do local de operação carregados:', personResponse);
            },
            error: (error) => {
              console.error('🏢 [OPERATION-LOCATION] Erro ao carregar dados do local de operação:', error);
              this.isLoadingOperationLocationData = false;
              this.cdr.detectChanges();
            }
          });

        } else {
          console.warn('🏢 [OPERATION-LOCATION] Veículo não possui local de operação definido');
          this.isLoadingOperationLocationData = false;
          this.cdr.detectChanges();

        }
    
  }

  /**
   * 🏠 Carregar dados do motorista
   */
  private loadDriverData(): void {
    if (!this.vehicleData?.id) {
      console.warn('🏠 [DRIVER] ID do veículo não encontrado');
      return;
    }

    if (this.vehicleData.driverId) {
      this.isLoadingDriverData = true;
    
    this.driversService.getById(Number(this.vehicleData.driverId)).pipe(
      takeUntil(this.destroy$)
      ).subscribe({
        next: async (response) => {
          this.driverData = response.data;
          await this.processDriverAddress();
          this.isLoadingDriverData = false;
          this.cdr.detectChanges();
          
          console.log('🏠 [DRIVER] Dados do motorista carregados:', response);
        },
        error: (error) => {
          console.error('🏠 [DRIVER] Erro ao carregar dados do motorista:', error);
          this.isLoadingDriverData = false;
          this.cdr.detectChanges();
        }
      });
    }

    
  }

  /**
   * 🏢 Processar endereço do local de operação
   */
  private async processOperationLocationAddress(): Promise<void> {
    if (!this.operationLocationData) return;
    
    // Construir endereço completo do local de operação
    const addressParts = [
      this.operationLocationData.address_street,
      this.operationLocationData.address_number,
      this.operationLocationData.address_neighborhood,
      this.operationLocationData.address_city,
      this.operationLocationData.address_uf,
      this.operationLocationData.address_cep
    ].filter(part => part && part.trim() !== '');

    this.operationLocationAddress = addressParts.join(', ');

    // Se temos coordenadas do endereço, usar diretamente
    if (this.operationLocationData.address_latitude && this.operationLocationData.address_longitude) {
      this.operationLocation = {
        lat: parseFloat(this.operationLocationData.address_latitude),
        lng: parseFloat(this.operationLocationData.address_longitude)
      };
      console.log('🏢 [OPERATION-LOCATION] Coordenadas do local de operação:', this.operationLocation);
    } else if (this.operationLocationAddress) {
      // Caso contrário, geocodificar o endereço
      const coordenadas = await this.getCoordinatesFromAddress(this.operationLocationAddress);
      if (coordenadas) {
        this.operationLocation = {
          lat: coordenadas.lat,
          lng: coordenadas.lng
        };
        console.log('🏢 [OPERATION-LOCATION] Endereço geocodificado:', this.operationLocation);
      }
    }
  }

  /**
   * 🏠 Processar endereço do motorista
   */
  private async processDriverAddress(): Promise<void> {
    if (!this.driverData) return;
    
    const coordenadas = await this.getCoordinatesFromAddress( `${this.driverData.address_street} ${this.driverData.address_number} ${this.driverData.address_neighborhood} ${this.driverData.address_city} ${this.driverData.address_uf} ${this.driverData.address_cep}`   || '');
    if (coordenadas) {
      this.driverHomeLocation = {
        lat: coordenadas.lat,
        lng: coordenadas.lng
      };
    }
    // Construir endereço completo
    const addressParts = [
      this.driverData.address_street,
      this.driverData.address_number,
      this.driverData.address_neighborhood,
      this.driverData.address_city,
      this.driverData.address_uf,
      this.driverData.address_cep
    ].filter(part => part && part.trim() !== '');

    this.driverAddress = addressParts.join(', ');

    // Se temos coordenadas do endereço, usar diretamente
    if (this.driverData.address_latitude && this.driverData.address_longitude) {
      this.driverHomeLocation = {
        lat: parseFloat(this.driverData.address_latitude),
        lng: parseFloat(this.driverData.address_longitude)
      };
      console.log('🏠 [DRIVER] Coordenadas da residência:', this.driverHomeLocation);
    } else if (this.driverAddress) {
      // Caso contrário, geocodificar o endereço
      this.geocodeDriverAddress();
    }
  }

  /**
   * 📍 Obter coordenadas (lat/lng) a partir de um endereço
   * @param address Endereço completo para geocodificar
   * @returns Promise com as coordenadas ou null se não encontrar
   */
  async getCoordinatesFromAddress(address: string): Promise<{ lat: number; lng: number } | null> {
    if (!address || address.trim() === '') {
      console.warn('📍 [GEOCODING] Endereço vazio fornecido');
      return null;
    }

    try {
      console.log('📍 [GEOCODING] Buscando coordenadas para:', address);
      
      const results = await this.geocodingService.geocode(address).toPromise();
      
      if (results && results.length > 0) {
        const result = results[0];
        const coordinates = {
          lat: result.latitude,
          lng: result.longitude
        };
        
        console.log('📍 [GEOCODING] Coordenadas encontradas:', coordinates);
        return coordinates;
      } else {
        console.warn('📍 [GEOCODING] Nenhum resultado encontrado para:', address);
        return null;
      }
    } catch (error) {
      console.error('📍 [GEOCODING] Erro ao geocodificar endereço:', error);
      return null;
    }
  }

  /**
   * 📍 Versão Observable do método de geocodificação
   * @param address Endereço completo para geocodificar
   * @returns Observable com as coordenadas
   */
  getCoordinatesFromAddressObservable(address: string): Observable<{ lat: number; lng: number } | null> {
    if (!address || address.trim() === '') {
      console.warn('📍 [GEOCODING] Endereço vazio fornecido');
      return of(null);
    }

    return this.geocodingService.geocode(address).pipe(
      map(results => {
        if (results && results.length > 0) {
          const result = results[0];
          const coordinates = {
            lat: result.latitude,
            lng: result.longitude
          };
          console.log('📍 [GEOCODING] Coordenadas encontradas:', coordinates);
          return coordinates;
        } else {
          console.warn('📍 [GEOCODING] Nenhum resultado encontrado para:', address);
          return null;
        }
      }),
      catchError(error => {
        console.error('📍 [GEOCODING] Erro ao geocodificar endereço:', error);
        return of(null);
      })
    );
  }

  /**
   * 🗺️ Geocodificar endereço do motorista
   */
  private geocodeDriverAddress(): void {
    if (!this.driverAddress) return;

    this.geocodingService.geocode(this.driverAddress).pipe(
      takeUntil(this.destroy$)
    ).subscribe({
      next: (results) => {
        if (results && results.length > 0) {
          const result = results[0];
          this.driverHomeLocation = {
            lat: result.latitude,
            lng: result.longitude
          };
          console.log('🏠 [DRIVER] Endereço geocodificado:', this.driverHomeLocation);
          this.cdr.detectChanges();
        }
      },
      error: (error) => {
        console.error('🏠 [DRIVER] Erro ao geocodificar endereço:', error);
      }
    });
  }

  /**
   * 🏠 Obter endereço do motorista para exibição
   */
  getAddressDriver(): string {
    if (this.isLoadingDriverData) {
      return 'Carregando...';
    }
    
    if (!this.driverAddress) {
      return 'Endereço não disponível';
    }
    
    return this.driverAddress;
  }

  /**
   * 🏢 Obter endereço do local de operação para exibição
   */
  getOperationLocationAddress(): string {
    if (this.isLoadingOperationLocationData) {
      return 'Carregando...';
    }
    
    if (!this.operationLocationAddress) {
      return 'Local de operação não definido';
    }
    
    return this.operationLocationAddress;
  }

  /**
   * 📍 EXEMPLO: Como usar os métodos de geocodificação
   */
  async exemploUsoGeocodificacao(): Promise<void> {
    const endereco = "Av. Paulista, 1000 - Bela Vista, São Paulo - SP";
    
    // Método 1: Usando async/await (Promise)
    const coordenadas = await this.getCoordinatesFromAddress(endereco);
    if (coordenadas) {
      console.log('Coordenadas encontradas:', coordenadas);
      // Resultado: { lat: -23.5629, lng: -46.6544 }
      
      // Usar as coordenadas para marcar no mapa, calcular distância, etc.
      this.marcarPontoNoMapa(coordenadas.lat, coordenadas.lng, endereco);
    }

    // Método 2: Usando Observable (reativo)
    this.getCoordinatesFromAddressObservable(endereco).subscribe(coords => {
      if (coords) {
        console.log('Coordenadas via Observable:', coords);
        // Fazer algo com as coordenadas...
      }
    });

    // Método 3: Geocodificar múltiplos endereços
    const enderecos = [
      "Rua Augusta, 123 - Consolação, São Paulo - SP",
      "Av. Faria Lima, 456 - Itaim Bibi, São Paulo - SP",
      "Rua Oscar Freire, 789 - Jardins, São Paulo - SP"
    ];

    for (const addr of enderecos) {
      const coords = await this.getCoordinatesFromAddress(addr);
      if (coords) {
        console.log(`${addr} -> Lat: ${coords.lat}, Lng: ${coords.lng}`);
      }
    }
  }

  /**
   * 📍 Exemplo: Marcar ponto customizado no mapa
   */
  private marcarPontoNoMapa(lat: number, lng: number, endereco: string): void {
    this.markerCounter++;
    const marker = {
      id: `custom-${Date.now()}`,
      lat: lat,
      lon: lng,
      address: endereco,
      timestamp: new Date(),
      markerIndex: this.markerCounter
    };

    this.selectedMarkers.push(marker);
    this.updateMapWithMarkers();
    
    console.log('📍 Ponto marcado no mapa:', marker);
  }

  /**
   * 🏠 Marcar residência do motorista no mapa
   */
  onDriverHomeClick(): void {
    if (!this.driverHomeLocation) {
      console.warn('🏠 [DRIVER-HOME] Localização da residência não encontrada');
      return;
    }

    // Limpar marcadores existentes
    this.selectedMarkers = [];
    this.markerCounter = 0;

    // Adicionar marcador especial para residência
    this.markerCounter++;
    const homeMarker = {
      id: `driver-home`,
      lat: this.driverHomeLocation.lat,
      lon: this.driverHomeLocation.lng,
      address: this.driverAddress,
      timestamp: new Date(),
      markerIndex: this.markerCounter
    };

    this.selectedMarkers.push(homeMarker);
    
    console.log('🏠 [DRIVER-HOME] Marcando residência no mapa:', {
      address: this.driverAddress,
      coordinates: `${this.driverHomeLocation.lat}, ${this.driverHomeLocation.lng}`
    });

    // Atualizar mapa
    this.updateMapWithMarkers();
  }

  /**
   * 🏠 Verificar se o veículo está próximo da residência do motorista
   */
  isNearDriverHome(): boolean {
    if (!this.driverHomeLocation || !this.vehicleData?.last_latitude || !this.vehicleData?.last_longitude) {
      return false;
    }

    const distance = this.calculateDistance(
      typeof this.vehicleData.last_latitude === 'string' ? parseFloat(this.vehicleData.last_latitude) : this.vehicleData.last_latitude,
      typeof this.vehicleData.last_longitude === 'string' ? parseFloat(this.vehicleData.last_longitude) : this.vehicleData.last_longitude,
      this.driverHomeLocation.lat,
      this.driverHomeLocation.lng
    );

    // Considerar "próximo" se estiver dentro de 500m da residência
    return distance <= 500;
  }

  /**
   * 🏠 Obter distância até a residência do motorista
   */
  getDistanceToDriverHome(): string {
    if (!this.driverHomeLocation || !this.vehicleData?.last_latitude || !this.vehicleData?.last_longitude) {
      return '';
    }

    const distance = this.calculateDistance(
      typeof this.vehicleData.last_latitude === 'string' ? parseFloat(this.vehicleData.last_latitude) : this.vehicleData.last_latitude,
      typeof this.vehicleData.last_longitude === 'string' ? parseFloat(this.vehicleData.last_longitude) : this.vehicleData.last_longitude,
      this.driverHomeLocation.lat,
      this.driverHomeLocation.lng
    );

    return this.formatDistance(distance);
  }

  /**
   * 🏢 Verificar se o veículo está próximo do local de operação
   */
  isNearOperationLocation(): boolean {
    if (!this.operationLocation || !this.vehicleData?.last_latitude || !this.vehicleData?.last_longitude) {
      return false;
    }

    const distance = this.calculateDistance(
      typeof this.vehicleData.last_latitude === 'string' ? parseFloat(this.vehicleData.last_latitude) : this.vehicleData.last_latitude,
      typeof this.vehicleData.last_longitude === 'string' ? parseFloat(this.vehicleData.last_longitude) : this.vehicleData.last_longitude,
      this.operationLocation.lat,
      this.operationLocation.lng
    );

    // Considerar "próximo" se estiver dentro de 1km do local de operação
    return distance <= 1000;
  }

  /**
   * 🏢 Obter distância até o local de operação
   */
  getDistanceToOperationLocation(): string {
    if (!this.operationLocation || !this.vehicleData?.last_latitude || !this.vehicleData?.last_longitude) {
      return '';
    }

    const distance = this.calculateDistance(
      typeof this.vehicleData.last_latitude === 'string' ? parseFloat(this.vehicleData.last_latitude) : this.vehicleData.last_latitude,
      typeof this.vehicleData.last_longitude === 'string' ? parseFloat(this.vehicleData.last_longitude) : this.vehicleData.last_longitude,
      this.operationLocation.lat,
      this.operationLocation.lng
    );

    return this.formatDistance(distance);
  }

  /**
   * 🏢 Marcar local de operação no mapa
   */
  onOperationLocationClick(): void {
    if (!this.operationLocation) {
      console.warn('🏢 [OPERATION-LOCATION] Localização do local de operação não encontrada');
      return;
    }

    // Limpar marcadores existentes
    this.selectedMarkers = [];
    this.markerCounter = 0;

    // Adicionar marcador especial para local de operação
    this.markerCounter++;
    const operationMarker = {
      id: `operation-location`,
      lat: this.operationLocation.lat,
      lon: this.operationLocation.lng,
      address: this.operationLocationAddress,
      timestamp: new Date(),
      markerIndex: this.markerCounter
    };

    this.selectedMarkers.push(operationMarker);
    
    console.log('🏢 [OPERATION-LOCATION] Marcando local de operação no mapa:', {
      address: this.operationLocationAddress,
      coordinates: `${this.operationLocation.lat}, ${this.operationLocation.lng}`
    });

    // Atualizar mapa
    this.updateMapWithMarkers();
  }

  /**
   * 🚀 Marcar no mapa onde ocorreu a velocidade máxima
   */
  onMaxSpeedClick(): void {
    if (!this.maxSpeedLocation) {
      console.warn('🚀 [MAX-SPEED] Localização da velocidade máxima não encontrada');
      return;
    }

    // Limpar marcadores existentes
    this.selectedMarkers = [];
    this.markerCounter = 0;

    // Adicionar marcador especial para velocidade máxima
    this.markerCounter++;
    const maxSpeedMarker = {
      id: `max-speed-${this.maxSpeedLocation.id}`,
      lat: this.maxSpeedLocation.latitude,
      lon: this.maxSpeedLocation.longitude,
      address: this.maxSpeedLocation.address,
      timestamp: this.maxSpeedLocation.timestamp,
      markerIndex: this.markerCounter
    };

    this.selectedMarkers.push(maxSpeedMarker);
    
    console.log('🚀 [MAX-SPEED] Marcando velocidade máxima no mapa:', {
      speed: this.speedStats.maxSpeed,
      location: this.maxSpeedLocation.address,
      coordinates: `${this.maxSpeedLocation.latitude}, ${this.maxSpeedLocation.longitude}`,
      timestamp: this.maxSpeedLocation.timestamp
    });

    // Atualizar mapa
    this.updateMapWithMarkers();
  }

  /**
   * 🚦 Determinar status do veículo baseado na ignição e velocidade
   */
  private getStatusFromIgnition(ignitionStatus: string, speed: number): 'em-movimento' | 'estacionado' | 'parado' {
    if (ignitionStatus === 'off') {
      return 'estacionado';
    } else if (speed > 5) { // Considerando velocidade > 5 km/h como movimento
      return 'em-movimento';
    } else {
      return 'parado';
    }
  }

  /**
   * 📏 Calcular distância entre duas coordenadas usando fórmula de Haversine
   * @param lat1 Latitude do ponto 1
   * @param lon1 Longitude do ponto 1
   * @param lat2 Latitude do ponto 2
   * @param lon2 Longitude do ponto 2
   * @returns Distância em metros
   */
  private calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
    const R = 6371000; // Raio da Terra em metros
    const dLat = this.toRadians(lat2 - lat1);
    const dLon = this.toRadians(lon2 - lon1);
    
    const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
              Math.cos(this.toRadians(lat1)) * Math.cos(this.toRadians(lat2)) *
              Math.sin(dLon / 2) * Math.sin(dLon / 2);
    
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c; // Distância em metros
  }

  /**
   * 🔄 Converter graus para radianos
   */
  private toRadians(degrees: number): number {
    return degrees * (Math.PI / 180);
  }



  /**
   * 🏃 Calcular estatísticas de velocidade do histórico
   */
  private calculateSpeedStats(): void {
    if (!this.locationHistory || this.locationHistory.length === 0) {
      this.speedStats = {
        maxSpeed: 0,
        mostFrequentSpeed: 0,
        averageSpeed: 0,
        totalReadings: 0
      };
      return;
    }

    const speeds = this.locationHistory.map(item => item.speed);
    
    // Maior velocidade e sua localização
    this.speedStats.maxSpeed = Math.max(...speeds);
    
    // Encontrar a localização onde ocorreu a velocidade máxima
    this.maxSpeedLocation = this.locationHistory.find(item => item.speed === this.speedStats.maxSpeed) || null;
    
    // Velocidade média
    this.speedStats.averageSpeed = Math.round(speeds.reduce((sum, speed) => sum + speed, 0) / speeds.length);
    
    // Total de leituras
    this.speedStats.totalReadings = speeds.length;
    
    // Velocidade mais frequente
    const speedFrequency = new Map<number, number>();
    
    // Filtrar velocidades muito baixas para análise de frequência
    const significantSpeeds = speeds.filter(speed => speed >= 5); // Apenas velocidades >= 5 km/h
    
    if (significantSpeeds.length > 0) {
      // Usar velocidades significativas para calcular frequência
      significantSpeeds.forEach(speed => {
        const roundedSpeed = Math.round(speed / 10) * 10; // Agrupar por faixas de 10 km/h
        speedFrequency.set(roundedSpeed, (speedFrequency.get(roundedSpeed) || 0) + 1);
      });
    } else {
      // Se não há velocidades significativas, usar todas
      speeds.forEach(speed => {
        const roundedSpeed = Math.round(speed / 5) * 5; // Agrupar por faixas de 5 km/h
        speedFrequency.set(roundedSpeed, (speedFrequency.get(roundedSpeed) || 0) + 1);
      });
    }
    
    console.log('🏃 [DEBUG] Velocidades originais:', speeds);
    console.log('🏃 [DEBUG] Velocidades significativas (>=5):', significantSpeeds);
    console.log('🏃 [DEBUG] Frequências por faixa:', Array.from(speedFrequency.entries()));
    
    let maxFrequency = 0;
    let mostFrequent = 0;
    speedFrequency.forEach((frequency, speed) => {
      if (frequency > maxFrequency) {
        maxFrequency = frequency;
        mostFrequent = speed;
      }
    });
    
    // Se não encontrou nenhuma velocidade frequente, usar a velocidade média como fallback
    if (mostFrequent === 0 && this.speedStats.averageSpeed > 0) {
      mostFrequent = Math.round(this.speedStats.averageSpeed / 10) * 10;
    }
    
    this.speedStats.mostFrequentSpeed = mostFrequent;
    
    console.log('🏃 [SPEED-STATS] Estatísticas calculadas:', this.speedStats);
    console.log('🏃 [DEBUG] Velocidade mais frequente:', mostFrequent, 'com', maxFrequency, 'ocorrências');
  }

  /**
   * 🛑 Calcular estatísticas de paradas e estacionamentos
   */
  private calculateStopStats(): void {
    if (!this.locationHistory || this.locationHistory.length === 0) {
      this.stopStats = {
        totalStops: 0,
        totalParked: 0,
        totalStopTime: 0,
        totalParkedTime: 0,
        formattedStopTime: '0min',
        formattedParkedTime: '0min'
      };
      return;
    }

    let totalStops = 0;
    let totalParked = 0;
    let totalStopTimeMinutes = 0;
    let totalParkedTimeMinutes = 0;

    // Analisar cada item do histórico
    this.locationHistory.forEach(item => {
      if (item.status === 'parado') {
        totalStops++;
        // Se tem duração definida, somar ao tempo total
        if (item.duration) {
          const minutes = this.parseDurationToMinutes(item.duration);
          totalStopTimeMinutes += minutes;
          console.log('🛑 [STOP-STATS] Parada encontrada:', {
            address: item.address.substring(0, 30) + '...',
            duration: item.duration,
            minutes: minutes
          });
        }
      } else if (item.status === 'estacionado') {
        totalParked++;
        // Se tem duração definida, somar ao tempo total
        if (item.duration) {
          const minutes = this.parseDurationToMinutes(item.duration);
          totalParkedTimeMinutes += minutes;
          console.log('🛑 [STOP-STATS] Estacionamento encontrado:', {
            address: item.address.substring(0, 30) + '...',
            duration: item.duration,
            minutes: minutes
          });
        }
      }
    });

    // Atualizar estatísticas
    this.stopStats = {
      totalStops,
      totalParked,
      totalStopTime: totalStopTimeMinutes,
      totalParkedTime: totalParkedTimeMinutes,
      formattedStopTime: this.formatMinutesToDuration(totalStopTimeMinutes),
      formattedParkedTime: this.formatMinutesToDuration(totalParkedTimeMinutes)
    };

    console.log('🛑 [STOP-STATS] Estatísticas finais calculadas:', {
      totalStops,
      totalParked,
      totalStopTimeMinutes,
      totalParkedTimeMinutes,
      formattedStopTime: this.stopStats.formattedStopTime,
      formattedParkedTime: this.stopStats.formattedParkedTime
    });
  }

  /**
   * 🕐 Converter string de duração para minutos
   * @param duration String como "2h 30min", "45min", "1h"
   * @returns Número de minutos
   */
  private parseDurationToMinutes(duration: string): number {
    let totalMinutes = 0;
    
    // Extrair horas (ex: "2h")
    const hoursMatch = duration.match(/(\d+)h/);
    if (hoursMatch) {
      totalMinutes += parseInt(hoursMatch[1]) * 60;
    }
    
    // Extrair minutos (ex: "30min")
    const minutesMatch = duration.match(/(\d+)min/);
    if (minutesMatch) {
      totalMinutes += parseInt(minutesMatch[1]);
    }
    
    return totalMinutes;
  }

  /**
   * 🕐 Converter minutos para string de duração formatada
   * @param totalMinutes Número total de minutos
   * @returns String formatada como "2h 30min" ou "45min"
   */
  formatMinutesToDuration(totalMinutes: number): string {
    if (totalMinutes === 0) return '0min';
    
    const hours = Math.floor(totalMinutes / 60);
    const minutes = totalMinutes % 60;
    
    if (hours > 0 && minutes > 0) {
      return `${hours}h ${minutes}min`;
    } else if (hours > 0) {
      return `${hours}h`;
    } else {
      return `${minutes}min`;
    }
  }

  /**
   * 🗝️ Gerar chave de cache baseada em grid de coordenadas
   * Agrupa coordenadas próximas para reutilizar endereços
   */
  private getCacheKey(lat: number, lon: number): string {
    // Arredondar coordenadas para criar "grid" de cache
    const gridLat = Math.floor(lat * 10000) / 10000; // ~11m de precisão
    const gridLon = Math.floor(lon * 10000) / 10000;
    return `${gridLat},${gridLon}`;
  }

  /**
   * 🎯 Buscar endereço com cache inteligente
   * Evita chamadas desnecessárias à API do Google
   */
  private getAddressWithCache(lat: number, lon: number): Observable<string> {
    const cacheKey = this.getCacheKey(lat, lon);
    
    // Verificar cache primeiro
    if (this.geocodingCache.has(cacheKey)) {
      console.log('🎯 [GEOCODING-CACHE] Cache hit para:', cacheKey);
      return of(this.geocodingCache.get(cacheKey)!);
    }

    // Verificar se já existe uma requisição pendente para evitar duplicatas
    if (this.pendingGeocodingRequests.has(cacheKey)) {
      console.log('🎯 [GEOCODING-CACHE] Reutilizando requisição pendente para:', cacheKey);
      return this.pendingGeocodingRequests.get(cacheKey)!;
    }

    // Fazer nova requisição
    console.log('🎯 [GEOCODING-CACHE] Nova requisição para:', cacheKey);
    const request$ = this.geocodingService.reverseGeocode(lat, lon).pipe(
      map(result => {
        const address = result.formattedAddress || 'Endereço não disponível';
        // Salvar no cache
        this.geocodingCache.set(cacheKey, address);
        // Remover da lista de pendentes
        this.pendingGeocodingRequests.delete(cacheKey);
        return address;
      }),
      catchError(error => {
        console.warn('🎯 [GEOCODING-CACHE] Erro ao buscar endereço:', error);
        // Remover da lista de pendentes
        this.pendingGeocodingRequests.delete(cacheKey);
        // Retornar fallback
        const fallbackAddress = 'Endereço não disponível';
        this.geocodingCache.set(cacheKey, fallbackAddress);
        return of(fallbackAddress);
      }),
      share() // Compartilhar resultado entre múltiplos subscribers
    );

    // Adicionar à lista de pendentes
    this.pendingGeocodingRequests.set(cacheKey, request$);
    return request$;
  }

  /**
   * 🚀 Processar endereços em lotes com rate limiting
   * Otimiza performance e reduz custos da API
   */
  private batchProcessAddresses(locations: LocationHistoryItem[]): Observable<LocationHistoryItem[]> {
    if (!locations || locations.length === 0) {
      return of([]);
    }

    console.log('🎯 [BATCH-GEOCODING] Processando', locations.length, 'endereços em lotes de', this.BATCH_SIZE);

    // Dividir em lotes
    const batches: LocationHistoryItem[][] = [];
    for (let i = 0; i < locations.length; i += this.BATCH_SIZE) {
      batches.push(locations.slice(i, i + this.BATCH_SIZE));
    }

    // Processar lotes sequencialmente com delay
    return from(batches).pipe(
      concatMap((batch, batchIndex) => {
        console.log('🎯 [BATCH-GEOCODING] Processando lote', batchIndex + 1, 'de', batches.length);
        
        // Processar itens do lote em paralelo
        const batchRequests = batch.map(location => 
          this.getAddressWithCache(location.latitude, location.longitude).pipe(
            map(address => ({
              ...location,
              address: address,
              city: this.extractCityFromAddress(address),
              state: this.extractStateFromAddress(address)
            }))
          )
        );

        // Aguardar todos os itens do lote
        return forkJoin(batchRequests).pipe(
          // Adicionar delay entre lotes (exceto no último)
          delay(batchIndex < batches.length - 1 ? this.RATE_LIMIT_DELAY : 0)
        );
      }),
      // Combinar todos os lotes em um array único
      scan((acc: LocationHistoryItem[], batch: LocationHistoryItem[]) => [...acc, ...batch], []),
      // Retornar apenas o resultado final
      takeLast(1)
    );
  }

  /**
   * 🏙️ Extrair cidade do endereço formatado
   */
  private extractCityFromAddress(address: string): string {
    // Lógica simples para extrair cidade (pode ser melhorada)
    const parts = address.split(',');
    if (parts.length >= 3) {
      return parts[parts.length - 3].trim();
    }
    return 'Cidade não informada';
  }

  /**
   * 🗺️ Extrair estado do endereço formatado
   */
  private extractStateFromAddress(address: string): string {
    // Lógica simples para extrair estado (pode ser melhorada)
    const parts = address.split(',');
    if (parts.length >= 2) {
      const statePart = parts[parts.length - 2].trim();
      // Extrair apenas a sigla do estado (ex: "SP 01234-567" -> "SP")
      const stateMatch = statePart.match(/^([A-Z]{2})/);
      return stateMatch ? stateMatch[1] : statePart;
    }
    return 'Estado não informado';
  }

  /**
   * 🎯 Agrupar localizações próximas para otimizar chamadas à API
   * @param locations Array de localizações da API
   * @returns Array de clusters otimizados
   */
  private clusterLocations(locations: VehicleLocationApiResponse[]): LocationCluster[] {
    if (!locations || locations.length === 0) return [];

    // Ordenar por timestamp (mais recente primeiro)
    const sortedLocations = [...locations].sort((a, b) => 
      new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
    );

    const clusters: LocationCluster[] = [];
    const processed = new Set<number>();

    console.log('🎯 [CLUSTERING] Iniciando agrupamento de', sortedLocations.length, 'pontos');

    for (let i = 0; i < sortedLocations.length; i++) {
      if (processed.has(i)) continue;

      const currentPoint = sortedLocations[i];
      const cluster: LocationCluster = {
        representativePoint: currentPoint,
        clusteredPoints: [currentPoint],
        startTime: new Date(currentPoint.timestamp),
        endTime: new Date(currentPoint.timestamp),
        duration: 0,
        status: this.getStatusFromIgnition(currentPoint.ignition_status, currentPoint.speed),
        averagePosition: { lat: currentPoint.lat, lon: currentPoint.lon },
        totalDistance: 0
      };

      processed.add(i);

      // Procurar pontos próximos para agrupar
      for (let j = i + 1; j < sortedLocations.length; j++) {
        if (processed.has(j)) continue;

        const nextPoint = sortedLocations[j];
        const distance = this.calculateDistance(
          currentPoint.lat, currentPoint.lon,
          nextPoint.lat, nextPoint.lon
        );

        const timeDiff = Math.abs(
          new Date(currentPoint.timestamp).getTime() - new Date(nextPoint.timestamp).getTime()
        ) / (1000 * 60); // diferença em minutos

        // Critérios para agrupamento
        const shouldCluster = this.shouldClusterPoints(
          currentPoint, nextPoint, distance, timeDiff
        );

        if (shouldCluster) {
          cluster.clusteredPoints.push(nextPoint);
          processed.add(j);

          // Atualizar informações do cluster
          cluster.endTime = new Date(Math.min(
            new Date(cluster.endTime).getTime(),
            new Date(nextPoint.timestamp).getTime()
          ));
          cluster.startTime = new Date(Math.max(
            new Date(cluster.startTime).getTime(),
            new Date(nextPoint.timestamp).getTime()
          ));
        }
      }

      // Calcular estatísticas finais do cluster
      this.finalizeCluster(cluster);
      clusters.push(cluster);
    }

    console.log('🎯 [CLUSTERING] Resultado:', clusters.length, 'clusters de', sortedLocations.length, 'pontos originais');
    console.log('🎯 [CLUSTERING] Redução de', 
      Math.round((1 - clusters.length / sortedLocations.length) * 100), '% nas chamadas API');

    return clusters;
  }

  /**
   * 🤔 Determinar se dois pontos devem ser agrupados
   */
  private shouldClusterPoints(
    point1: VehicleLocationApiResponse,
    point2: VehicleLocationApiResponse,
    distance: number,
    timeDiffMinutes: number
  ): boolean {
    const MIN_DISTANCE = 200; // 200 metros
    const MAX_TIME_GAP = 60; // 60 minutos máximo entre pontos do mesmo cluster

    // Não agrupar se o tempo entre pontos for muito grande
    if (timeDiffMinutes > MAX_TIME_GAP) {
      return false;
    }

    // Agrupar se a distância for pequena (mesmo local)
    if (distance < MIN_DISTANCE) {
      return true;
    }

    // Agrupar pontos parados/estacionados próximos no tempo e espaço
    const bothStopped = point1.speed < 10 && point2.speed < 10;
    const bothIgnitionOff = point1.ignition_status === 'off' && point2.ignition_status === 'off';
    const closeInTime = timeDiffMinutes < 30; // 30 minutos
    const reasonablyClose = distance < 500; // 500 metros

    if (bothStopped && closeInTime && reasonablyClose) {
      return true;
    }

    // Agrupar pontos com ignição desligada (estacionamento)
    if (bothIgnitionOff && distance < 300 && timeDiffMinutes < 45) {
      return true;
    }

    return false;
  }

  /**
   * ✅ Finalizar cálculos do cluster
   */
  private finalizeCluster(cluster: LocationCluster): void {
    const points = cluster.clusteredPoints;
    
    // Calcular posição média
    const avgLat = points.reduce((sum, p) => sum + p.lat, 0) / points.length;
    const avgLon = points.reduce((sum, p) => sum + p.lon, 0) / points.length;
    cluster.averagePosition = { lat: avgLat, lon: avgLon };

    // Calcular duração total
    cluster.duration = Math.abs(
      new Date(cluster.endTime).getTime() - new Date(cluster.startTime).getTime()
    ) / (1000 * 60); // em minutos

    // Calcular distância total percorrida no cluster
    let totalDistance = 0;
    for (let i = 1; i < points.length; i++) {
      totalDistance += this.calculateDistance(
        points[i-1].lat, points[i-1].lon,
        points[i].lat, points[i].lon
      );
    }
    cluster.totalDistance = totalDistance;

    // Determinar status final do cluster baseado em duração e velocidade
    const avgSpeed = points.reduce((sum, p) => sum + p.speed, 0) / points.length;
    const hasMovement = points.some(p => p.speed > 10);
    const hasIgnitionOff = points.some(p => p.ignition_status === 'off');
    
    // Lógica melhorada para determinar status
    if (cluster.duration >= 30 && avgSpeed < 5 && hasIgnitionOff) {
      // Mais de 30 minutos parado com ignição desligada = estacionado
      cluster.status = 'estacionado';
    } else if (cluster.duration >= 5 && avgSpeed < 10) {
      // Entre 5-30 minutos com baixa velocidade = parado
      cluster.status = 'parado';
    } else if (hasMovement && avgSpeed >= 10) {
      // Tem movimento significativo = em movimento
      cluster.status = 'em-movimento';
    } else {
      // Fallback baseado na velocidade média
      if (avgSpeed < 5) {
        cluster.status = cluster.duration >= 15 ? 'estacionado' : 'parado';
      } else {
        cluster.status = 'em-movimento';
      }
    }

    console.log('🎯 [CLUSTER]', {
      points: points.length,
      duration: Math.round(cluster.duration),
      distance: Math.round(cluster.totalDistance),
      status: cluster.status
    });
  }
} 