import { Injectable } from '@angular/core';
import { HttpParams } from '@angular/common/http';
import { Observable, of, BehaviorSubject, throwError } from 'rxjs';
import { catchError, map, tap, retry, timeout } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

import { Route, RouteFilters, RouteResponse, RouteMetrics } from './route.interface';
import { Logger } from '../../shared/services/logger/logger.service';
import { DomainService } from '../../shared/components/base-domain/base-domain.component';
import { ApiClientService } from '../../shared/services/api/api-client.service';
import { PaginatedResponse } from '../../shared/interfaces/paginate.interface';
import { Vehicle } from '../vehicles/vehicle.interface';
import { DateRangeShortcuts } from '../../shared/utils/date-range.utils';

/**
 * 🎯 RoutesService - Serviço de Gestão de Rotas PraFrota
 * 
 * Serviço principal para operações CRUD de rotas seguindo o padrão
 * do projeto com ApiClientService.
 * 
 * ✨ Funcionalidades:
 * - CRUD completo de rotas
 * - Sistema de fallback automático
 * - Monitoramento de conectividade
 * - Cache inteligente de dados
 * - Integração com dados mock realistas
 * - Logs detalhados para debugging
 * 
 * 🚀 Baseado na documentação técnica do módulo de rotas
 */
@Injectable({
  providedIn: 'root'
})
export class RoutesService implements DomainService<Route> {
  // private readonly apiUrl = 'https://prafrota-be-bff-tenant-api.grupopra.tech/route';
  // private readonly healthCheckUrl = 'https://prafrota-be-bff-tenant-api.grupopra.tech/health';
  
  // Estado de conectividade
  private isBackendAvailable$ = new BehaviorSubject<boolean>(true);
  // private lastHealthCheck = 0;
  // private healthCheckInterval = 30000; // 30 segundos
  
  // Cache de dados
  private routesCache: Route[] = [];
  // private lastCacheUpdate = 0;
  // private cacheTimeout = 300000; // 5 minutos
  private logger: Logger;

  constructor(
    private apiClient: ApiClientService,
    private httpClient: HttpClient
  ) {
    this.logger = new Logger('RoutesService');
    this.logger.log('🚀 RoutesService inicializado');
    
    // 🔄 Limpar cache e forçar nova geração de dados
    this.routesCache = [];
    this.routesDataCache = [];
    this.dataLoaded = false;
    // this.lastCacheUpdate = 0;
    
    // Carregar dados mock e iniciar monitoramento
    // this.loadRoutesFromFile();
    // this.startHealthMonitoring();
  }

  // ========================================
  // 🎯 IMPLEMENTAÇÃO DA INTERFACE DOMAINSERVICE
  // ========================================

  /**
   * 🔍 Método obrigatório da interface DomainService
   * Buscar entidades com paginação e filtros
  */
  getEntities(page: number, pageSize: number, filters: any): Observable<{
    data: Route[];
    totalCount: number;
    pageCount: number;
    currentPage: number;
  }> {

    // //TODO: Fazer o filtro de data inicial se o filtro de data for vazio
    // if (!filters.start_date && !filters.end_date) {
    //   filters = { ...filters, start_date : DateRangeShortcuts.today().date_start, end_date : DateRangeShortcuts.today().date_end };      
    // }

    return this.getRoutes(page, pageSize, filters).pipe(
        map(response => ({
            data: response.data,
            totalCount: response.totalCount,
            pageCount: response.pageCount,
            currentPage: response.currentPage
        }))
    );
  }
  // getEntities(page: number, pageSize: number, filters: any): Observable<{
  //   data: Route[];
  //   totalCount: number;
  //   pageCount: number;
  //   currentPage: number;
  // }> {
  //   return this.getRoutes(page, pageSize, filters as RouteFilters).pipe(
  //     map(response => ({
  //       data: response.data,
  //       totalCount: response.pagination.total,
  //       pageCount: response.pagination.totalPages,
  //       currentPage: response.pagination.page
  //     }))
  //   );
  // }

  /**
   * ✅ Método genérico para criar - chamado automaticamente pelo BaseDomainComponent
   */
  create(data: any): Observable<Route> {
    const newRoute = {
      ...data,
      routeId: `route_${Date.now()}`,
      createdAt: new Date(),
      updatedAt: new Date()
    } as Route;

    return this.apiClient.post<Route>('routes', newRoute).pipe(
      catchError(error => {
        console.warn('⚠️ Erro ao criar rota, simulando criação local', error);
        return of(newRoute);
      })
    );
  }

  /**
   * ✅ Método genérico para atualizar - chamado automaticamente pelo BaseDomainComponent
   */
  update(id: any, data: any): Observable<Route> {
    const updatedRoute = {
      ...data,
      routeId: id,
      updatedAt: new Date()
    } as Route;

    return this.apiClient.patch<Route>(`routes/${id}`, updatedRoute).pipe(
      catchError(error => {
        console.warn('⚠️ Erro ao atualizar rota, simulando atualização local', error);
        return of(updatedRoute);
      })
    );
  }

  /**
   * ✅ Método genérico para deletar - chamado automaticamente pelo BaseDomainComponent
   */
  delete(id: any): Observable<void> {
    return this.apiClient.delete<void>(`routes/${id}`).pipe(
      catchError(error => {
        console.warn('⚠️ Erro ao deletar rota, simulando exclusão local', error);
        return of(void 0);
      })
    );
  }

  // ========================================
  // 🎯 MÉTODOS ESPECÍFICOS DE ROTAS
  // ========================================

  /**
   * 🔍 Buscar rotas com paginação e filtros
   */
    getRoutes(
    page = 1, 
    limit = 10, 
    filters?: {[key: string]: string}
  ): Observable<PaginatedResponse<Route>> {
    
    console.log('🔍 [DEBUG] RoutesService.getRoutes called with:', {
      page,
      limit,
      filters,
      filtersType: typeof filters,
      filtersKeys: filters ? Object.keys(filters) : 'no filters'
    });
    
    let url = `route?page=${page}&limit=${limit}`;
    
    if (filters) {
        const params = new URLSearchParams();
        
        for (const [key, value] of Object.entries(filters)) {
            if (value) {
                params.append(key, value);
                console.log(`✅ [DEBUG] Added filter param: ${key} = ${value}`);
            } else {
                console.log(`⚠️ [DEBUG] Skipped empty filter: ${key} = ${value}`);
            }
        }
        
        if (params.toString()) {
          url += `&${params.toString()}`;
        }
    }
    
    console.log('🌐 [DEBUG] Final API URL:', url);
    return this.apiClient.get<PaginatedResponse<Route>>(url);
  }

  //   page = 1,
  //   limit = 500,
  //   filters?: RouteFilters
  // ): Observable<RouteResponse> {
    
  //   console.log(`🔍 Buscando rotas - Página: ${page}, Limite: ${limit}`);

  //   // Verificar se backend está disponível
  //   if (!this.isBackendAvailable$.value) {
  //     console.log('🔄 Backend indisponível, carregando dados do arquivo JSON...');
  //     return this.loadRoutesFromFile().pipe(
  //       map(routes => this.processRoutesData(routes, page, limit, filters))
  //     );
  //   }

  //   // Tentar buscar do backend primeiro
  //   let url = `${this.apiUrl}?page=${page}&limit=${limit}`;
    
  //   if (filters) {
  //     const params = new URLSearchParams();
      
  //     for (const [key, value] of Object.entries(filters)) {
  //       if (value) {
  //         params.append(key, value.toString());
  //       }
  //     }
      
  //     if (params.toString()) {
  //       url += `&${params.toString()}`;
  //     }
  //   }

  //   return this.apiClient.get<RouteResponse>(url).pipe(
  //     timeout(10000),
  //     retry(2),
  //     tap(response => {
  //       console.log('✅ Dados recebidos do backend:', response);
  //       this.updateCache(response.data);
  //     }),
  //     catchError(error => {
  //       console.warn('⚠️ Backend indisponível, usando dados do arquivo JSON', error);
        
  //       return this.loadRoutesFromFile().pipe(
  //         map(routes => this.processRoutesData(routes, page, limit, filters))
  //       );
  //     })
  //   );
  // }

  private processRoutesData(routes: Route[], page: number, limit: number, filters?: RouteFilters): RouteResponse {
    let filteredRoutes = [...routes];

    // Aplicar filtros se existirem
    if (filters) {
      if (filters.search) {
        const searchTerm = filters.search.toLowerCase();
        filteredRoutes = filteredRoutes.filter(route =>
          route.routeNumber?.toLowerCase().includes(searchTerm) ||
          route.driverName?.toLowerCase().includes(searchTerm) ||
          route.vehiclePlate?.toLowerCase().includes(searchTerm) ||
          route.origin?.city?.toLowerCase().includes(searchTerm) ||
          route.destination?.city?.toLowerCase().includes(searchTerm)
        );
      }

      if (filters.status && filters.status.length > 0) {
        filteredRoutes = filteredRoutes.filter(route => 
          filters.status!.includes(route.status)
        );
      }

      if (filters.type && filters.type.length > 0) {
        filteredRoutes = filteredRoutes.filter(route => 
          filters.type!.includes(route.type)
        );
      }

      if (filters.priority && filters.priority.length > 0) {
        filteredRoutes = filteredRoutes.filter(route => 
          filters.priority!.includes(route.priority)
        );
      }
    }

    // Ordenar por data de criação (mais recentes primeiro)
    filteredRoutes.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());

    // Aplicar paginação
    const startIndex = (page - 1) * limit;
    const endIndex = startIndex + limit;
    const paginatedRoutes = filteredRoutes.slice(startIndex, endIndex);

    const totalPages = Math.ceil(filteredRoutes.length / limit);

    console.log(`📊 Resultado da busca: ${paginatedRoutes.length}/${filteredRoutes.length} rotas (página ${page}/${totalPages})`);

    return {
      data: paginatedRoutes,
      pagination: {
        total: filteredRoutes.length,
        page: page,
        limit: limit,
        totalPages: totalPages
      },
      source: 'file',
      timestamp: new Date().toISOString()
    };
  }

  /**
   * 🆔 Buscar rota por ID
   */
  getById(id: string): Observable<Route> {
    return this.apiClient.get<Route>(`routes/${id}`).pipe(
      catchError(error => {
        console.warn('⚠️ Erro ao buscar rota, usando fallback', error);
        const fallbackRoute = this.routesDataCache.find(r => r.Id === id);
        if (fallbackRoute) {
          return of(fallbackRoute);
        }
        throw error;
      })
    );
  }

  /**
   * 📊 Obter métricas das rotas
   */
  // getRouteMetrics(): Observable<RouteMetrics> {
  //   return this.apiClient.get<RouteMetrics>(`${this.apiUrl}/metrics`).pipe(
  //     retry(2),
  //     catchError(error => {
  //       this.logger.warn('⚠️ Erro ao obter métricas, usando dados calculados', { error: error.message });
  //       return of(this.calculateMockMetrics());
  //     })
  //   );
  // }

  /**
   * 🔄 Verificar saúde do backend
   */
  // checkBackendHealth(): Observable<boolean> {
  //   const now = Date.now();
    
  //   // Evitar verificações muito frequentes
  //   if (now - this.lastHealthCheck < 5000) {
  //     return this.isBackendAvailable$.asObservable();
  //   }
    
  //   this.lastHealthCheck = now;
    
  //   return this.apiClient.get(this.healthCheckUrl).pipe(
  //     timeout(5000),
  //     map(() => {
  //       this.isBackendAvailable$.next(true);
  //       return true;
  //     }),
  //     catchError(() => {
  //       this.isBackendAvailable$.next(false);
  //       return of(false);
  //     })
  //   );
  // }

  /**
   * 🔔 Observable do status de conectividade
   */
  get isBackendAvailable(): Observable<boolean> {
    return this.isBackendAvailable$.asObservable();
  }

  // ========================================
  // 🎯 DADOS DE FALLBACK - AGORA DO ARQUIVO JSON
  // ========================================

  private routesDataCache: Route[] = [];
  private dataLoaded = false;

  // private loadRoutesFromFile(): Observable<Route[]> {
  //   if (this.dataLoaded && this.routesDataCache.length > 0) {
  //     console.log('📁 Usando cache dos dados do arquivo JSON');
  //     return of(this.routesDataCache);
  //   }
    
  //   return this.httpClient.get<Route[]>('/assets/data/routes-data_new.json').pipe(
  //     map((data: any) => {
  //       // Converter strings de data para objetos Date
  //       const processedData = data.data.map((route: any) => ({
  //         ...route,
  //         scheduledDeparture: new Date(route.scheduledDeparture),
  //         scheduledArrival: new Date(route.scheduledArrival),
  //         createdAt: new Date(route.createdAt),
  //         updatedAt: new Date(route.updatedAt),
  //         actualDeparture: route.actualDeparture ? new Date(route.actualDeparture) : undefined,
  //         actualArrival: route.actualArrival ? new Date(route.actualArrival) : undefined
  //       }));

  //       this.routesDataCache = processedData;
  //       this.dataLoaded = true;
        
  //       console.log(`✅ ${processedData.length} rotas carregadas do arquivo JSON!`);
  //       console.log('📊 Primeira rota carregada:', processedData[0]);
        
  //       return processedData;
  //     }),
  //     catchError(error => {
  //       console.error('❌ Erro ao carregar arquivo routes-data.json:', error);
  //       this.logger.error('Erro ao carregar dados do arquivo', error);
        
  //       // Fallback para array vazio em caso de erro
  //       return of([]);
  //     })
  //   );
  // }

  // ========================================
  // �� MÉTODOS PRIVADOS - UTILITÁRIOS
  // ========================================

  private calculateMockMetrics(): RouteMetrics {
    const routes = this.routesDataCache;
    const completedRoutes = routes.filter(r => r.status === 'completed');
    const onTimeRoutes = completedRoutes.filter(r => r.onTimeDelivery);

    return {
      totalRoutes: routes.length,
      completedRoutes: completedRoutes.length,
      onTimeDeliveryRate: completedRoutes.length > 0 ? (onTimeRoutes.length / completedRoutes.length) * 100 : 0,
      averageDeliveryTime: completedRoutes.reduce((sum, r) => sum + (r.actualDuration || 0), 0) / completedRoutes.length || 0,
      totalDistance: routes.reduce((sum, r) => sum + (r.totalDistance || 0), 0),
      totalRevenue: routes.reduce((sum, r) => sum + r.totalValue, 0),
      totalCosts: routes.reduce((sum, r) => sum + (r.fuelCost || 0) + (r.tollCost || 0) + (r.driverPayment || 0), 0),
      profitMargin: 0, // Calculado baseado em receita vs custos
      fuelEfficiency: routes.reduce((sum, r) => sum + (r.fuelConsumption || 0), 0) / routes.length || 0,
      customerSatisfaction: routes.reduce((sum, r) => sum + (r.customerRating || 4), 0) / routes.length || 4
    };
  }

  // ========================================
  // 🎯 MÉTODOS PRIVADOS - CACHE
  // ========================================

  // private updateCache(routes: Route[]): void {
  //   this.routesCache = routes;
  //   this.lastCacheUpdate = Date.now();
  // }

  private addToCache(route: Route): void {
    const index = this.routesCache.findIndex(r => r.Id === route.Id);
    if (index !== -1) {
      this.routesCache[index] = route;
    } else {
      this.routesCache.unshift(route);
    }
  }

  private updateInCache(route: Route): void {
    const index = this.routesCache.findIndex(r => r.Id === route.Id);
    if (index !== -1) {
      this.routesCache[index] = route;
    }
  }

  private removeFromCache(routeId: string): void {
    const index = this.routesCache.findIndex(r => r.Id === routeId);
    if (index !== -1) {
      this.routesCache.splice(index, 1);
    }
  }

  // private startHealthMonitoring(): void {
  //   setInterval(() => {
  //     this.checkBackendHealth().subscribe();
  //   }, this.healthCheckInterval);
  // }

  /**
   * 🔄 Forçar recarga dos dados do arquivo (método temporário para debug)
   */
  // forceReloadFromFile(): void {
  //   console.log('🔄 Forçando recarga dos dados do arquivo...');
  //   this.routesDataCache = [];
  //   this.routesCache = [];
  //   // this.lastCacheUpdate = 0;
  //   this.dataLoaded = false;
    
  //   this.loadRoutesFromFile().subscribe(routes => {
  //     console.log(`✅ ${routes.length} rotas recarregadas do arquivo!`);
  //   });
  // }
} 