import { Injectable } from '@angular/core';
import { Observable, of, BehaviorSubject, interval, EMPTY } from 'rxjs';
import { map, catchError, tap, switchMap, takeWhile } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

// Interfaces
import { 
  VehicleGpsTrack, 
  GpsTrackPoint, 
  GpsTrackFilters, 
  GpsTrackResponse,
  RealTimeGpsData,
  GpsMetrics,
  GpsAlert
} from '../interfaces/vehicle-gps.interface';

// Services
import { ApiClientService } from '../../../../shared/services/api/api-client.service';

/**
 * 🚗 VehicleGpsTrackService - Gestão de Rastreamento GPS
 * 
 * Service responsável por gerenciar dados de rastreamento GPS dos veículos,
 * incluindo histórico de posições, simulação em tempo real e análise de rotas.
 */
@Injectable({
  providedIn: 'root'
})
export class VehicleGpsTrackService {

  private isBackendAvailable$ = new BehaviorSubject<boolean>(false);
  private gpsTracksDataCache: VehicleGpsTrack[] = [];
  private dataLoaded = false;
  private realTimeSimulation$ = new BehaviorSubject<boolean>(false);
  private currentTrackSimulation: VehicleGpsTrack | null = null;
  private simulationIndex = 0;

  constructor(
    private apiClient: ApiClientService,
    private httpClient: HttpClient
  ) {
    console.log('🚀 [VehicleGpsTrack] Service inicializado');
    this.isBackendAvailable$.next(false);
    this.loadGpsTracksFromFile();
  }

  get isBackendAvailable(): Observable<boolean> {
    return this.isBackendAvailable$.asObservable();
  }

  get isOnline(): boolean {
    return this.isBackendAvailable$.value;
  }

  get isUsingFallback(): boolean {
    return !this.isBackendAvailable$.value;
  }

  private loadGpsTracksFromFile(): Observable<VehicleGpsTrack[]> {
    if (this.dataLoaded && this.gpsTracksDataCache.length > 0) {
      console.log('📁 [VehicleGpsTrack] Usando cache dos dados do arquivo JSON');
      return of(this.gpsTracksDataCache);
    }

    console.log('📁 [VehicleGpsTrack] Carregando dados do arquivo: /assets/data/vehicle-gps-track-data.json');
    
    return this.httpClient.get<VehicleGpsTrack[]>('/assets/data/vehicle-gps-track-data.json').pipe(
      map((data: VehicleGpsTrack[]) => {
        const processedData = data.map(track => ({
          ...track,
          startTime: new Date(track.startTime),
          endTime: track.endTime ? new Date(track.endTime) : undefined,
          trackPoints: track.trackPoints.map(point => ({
            ...point,
            timestamp: new Date(point.timestamp)
          }))
        }));

        this.gpsTracksDataCache = processedData;
        this.dataLoaded = true;
        
        console.log(`✅ [VehicleGpsTrack] ${processedData.length} tracks carregados do arquivo JSON!`);
        return processedData;
      }),
      catchError(error => {
        console.error('❌ [VehicleGpsTrack] Erro ao carregar arquivo vehicle-gps-track-data.json:', error);
        return of([]);
      })
    );
  }

  getGpsTrackByRouteId(routeId: string): Observable<VehicleGpsTrack | null> {
    console.log(`🚛 [VehicleGpsTrack] Buscando track por routeId: ${routeId}`);
    
    return this.loadGpsTracksFromFile().pipe(
      map(tracks => {
        const track = tracks.find(t => t.routeId === routeId);
        return track || null;
      })
    );
  }

  getSimpleGpsPoints(routeId: string): Observable<GpsTrackPoint[]> {
    return this.getGpsTrackByRouteId(routeId).pipe(
      map(track => track ? track.trackPoints : [])
    );
  }

  startRealTimeSimulation(routeId: string): Observable<GpsTrackPoint> {
    console.log(`🎬 [VehicleGpsTrack] Iniciando simulação em tempo real para rota: ${routeId}`);
    
    return this.getGpsTrackByRouteId(routeId).pipe(
      map(track => {
        if (!track || !track.trackPoints.length) {
          throw new Error(`Dados GPS não encontrados para rota ${routeId}`);
        }
        
        this.currentTrackSimulation = track;
        this.simulationIndex = 0;
        this.realTimeSimulation$.next(true);
        
        return track.trackPoints[0];
      })
    );
  }

  stopRealTimeSimulation(): void {
    console.log('⏸️ [VehicleGpsTrack] Parando simulação em tempo real');
    this.realTimeSimulation$.next(false);
    this.currentTrackSimulation = null;
    this.simulationIndex = 0;
  }

  /**
   * 🔥 CORRIGIDO: Observable da simulação GPS que NÃO causa loop infinito
   */
  getRealTimeSimulation(): Observable<GpsTrackPoint | null> {
    return this.realTimeSimulation$.pipe(
      switchMap(isRunning => {
        // Se não está rodando, retornar EMPTY para parar o observable
        if (!isRunning || !this.currentTrackSimulation) {
          return EMPTY;
        }
        
        // Se está rodando, iniciar o interval
        return interval(2000).pipe(
          map(() => {
            // Verificar novamente se ainda está rodando
            if (!this.realTimeSimulation$.value || !this.currentTrackSimulation) {
              return null;
            }
            
            const track = this.currentTrackSimulation;
            
            // Verificar se chegou ao fim antes de incrementar
            if (this.simulationIndex >= track.trackPoints.length) {
              console.log('🏁 [VehicleGpsTrack] Simulação concluída - chegou ao fim');
              this.stopRealTimeSimulation();
              return null;
            }
            
            const currentPoint = track.trackPoints[this.simulationIndex];
            this.simulationIndex++;
            
            console.log(`📡 [VehicleGpsTrack] Ponto atual: ${this.simulationIndex}/${track.trackPoints.length}`, currentPoint);
            return currentPoint;
          }),
          takeWhile(point => point !== null, true) // Incluir o último null antes de parar
        );
      })
    );
  }

  get isSimulationRunning(): Observable<boolean> {
    return this.realTimeSimulation$.asObservable();
  }

  /**
   * 📊 Verificar se simulação está rodando (síncrono)
   */
  get isSimulationRunningSyncronous(): boolean {
    return this.realTimeSimulation$.value;
  }

  getCurrentSimulatedPosition(): GpsTrackPoint | null {
    if (!this.currentTrackSimulation || this.simulationIndex <= 0) {
      return null;
    }
    
    return this.currentTrackSimulation.trackPoints[this.simulationIndex - 1] || null;
  }

  forceReloadFromFile(): void {
    console.log('🔄 [VehicleGpsTrack] Forçando recarga dos dados do arquivo...');
    this.gpsTracksDataCache = [];
    this.dataLoaded = false;
    
    this.loadGpsTracksFromFile().subscribe(tracks => {
      console.log(`✅ [VehicleGpsTrack] ${tracks.length} tracks recarregados do arquivo!`);
    });
  }

  clearCache(): void {
    this.gpsTracksDataCache = [];
    this.dataLoaded = false;
    this.stopRealTimeSimulation();
    console.log('🧹 [VehicleGpsTrack] Cache limpo');
  }
}
