import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { map, catchError, tap, filter, switchMap } from 'rxjs/operators';
import { ImageUploadService } from '../../components/image-uploader/image-uploader.service';

export interface AuthUser {
  id: string;
  name: string;
  email: string;
  access_level: string;
  tenant_id?: string;
  permissions?: string[];
  // 🆕 Campos adicionais do endpoint de detalhes
  avatar?: string;
  full_name?: string;
  phone?: string;
  department?: string;
  last_login?: string;
  created_at?: string;
  updated_at?: string;
}

export interface LoginResponse {
  success: boolean;
  data: {
    user: AuthUser;
    token: string;
    refresh_token?: string;
  };
  message?: string;
}

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private readonly TOKEN_KEY = 'prafrota_auth_token';
  private readonly REFRESH_TOKEN_KEY = 'prafrota_refresh_token';
  private readonly USER_KEY = 'prafrota_user_data';
  
  // 🎯 ESTADO REATIVO do usuário logado
  private currentUserSubject = new BehaviorSubject<AuthUser | null>(null);
  public currentUser$ = this.currentUserSubject.asObservable();
  
  // 🎯 ESTADO de autenticação
  private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
  public isAuthenticated$ = this.isAuthenticatedSubject.asObservable();

  constructor(
    private http: HttpClient,
    private router: Router,
    private imageUploadService: ImageUploadService
  ) {
    // 🚀 INICIALIZAR com dados salvos no localStorage
    this.initializeAuth();
  }

  /**
   * 🚀 INICIALIZAR autenticação ao carregar o service
   */
  private initializeAuth(): void {
    const token = this.getToken();
    const userData = this.getUserData();
    
    if (token && userData?.id) {
      console.log('🔐 Inicializando autenticação com dados do cache:', userData);
      
      // 🔄 Buscar dados completos via API
      this.fetchUserDetails(userData.id).subscribe({
        next: (completeUser) => {
          this.refreshUserData();
          // Atualizar cache local com dados completos
          this.setUserData(completeUser);
          this.currentUserSubject.next(completeUser);
          this.isAuthenticatedSubject.next(true);
          console.log('✅ Dados completos do usuário carregados via API:', completeUser);
        },
        error: (error) => {
          console.warn('⚠️ Falha ao carregar dados completos via API, usando cache:', error);
          // Fallback para dados do localStorage
          this.currentUserSubject.next(userData);
          this.isAuthenticatedSubject.next(true);
        }
      });
    } else {
      console.log('❌ Token ou dados do usuário não encontrados, limpando autenticação');
      this.clearAuth();
    }
  }

  /**
   * 🔑 LOGIN - Fazer login e armazenar dados
   */
  login(credentials: { email: string; password: string }): Observable<any> {
    const apiUrl = 'https://prafrota-be-bff-tenant-api.grupopra.tech/auth/signIn';
    
    // 🔑 Obter tenant_id do localStorage (necessário para autenticação)
    const tenantId = localStorage.getItem('tenant_id');
    if (!tenantId) {
      return new Observable(observer => {
        observer.error(new Error('Tenant ID não encontrado. Não é possível fazer login.'));
      });
    }

    const headers = { 
      'x-tenant-uuid': tenantId,
      'Content-Type': 'application/json'
    };
    
    return new Observable(observer => {
      this.http.post<any>(apiUrl, credentials, { headers }).subscribe({
        next: (response) => {
          console.log('🔍 Resposta da API de login:', response);
          console.log('🔍 Tipo da resposta:', typeof response);
          console.log('🔍 Keys da resposta:', Object.keys(response));
          
          if (response.data && response.data.accessToken) {
            // 💾 SALVAR token
            this.setToken(response.data.accessToken);
            
            // 🎯 CRIAR dados do usuário (podemos melhorar com endpoint específico depois)
            const userData: AuthUser = {
              id: this.extractUserIdFromToken(response.data.accessToken),
              name: credentials.email.split('@')[0].replace(/[._-]/g, ' '), // Nome mais limpo
              email: credentials.email,
              access_level: 'admin', // Nível padrão - pode ser obtido de endpoint específico
              tenant_id: tenantId
            };
            
            this.setUserData(userData);            
            
            // 🎯 ATUALIZAR estado reativo com dados básicos
            this.currentUserSubject.next(userData);
            this.isAuthenticatedSubject.next(true);
            
            console.log('✅ Login realizado com sucesso (dados básicos):', userData);
            
            // 🔄 BUSCAR dados completos via API após login
            this.fetchUserDetails(userData.id).subscribe({
              next: (completeUser) => {
                // Atualizar com dados completos
                this.setUserData(completeUser);
                this.currentUserSubject.next(completeUser);
                console.log('🎯 Dados completos carregados após login:', completeUser);
              },
              error: (error) => {
                console.warn('⚠️ Falha ao carregar dados completos após login, mantendo dados básicos:', error);
                // Manter dados básicos se API falhar
              }
            });
            
            // Retornar resposta simplificada (com dados básicos)
            const loginResponse = {
              success: true,
              data: {
                user: userData,
                token: response.data.accessToken
              }
            };
            
            observer.next(loginResponse);
            observer.complete();
          } else {
            observer.error(new Error('Resposta inválida da API de login'));
          }
        },
        error: (error) => {
          console.error('❌ Erro no login:', error);
          observer.error(error);
        }
      });
    });
  }

  /**
   * 🚪 LOGOUT - Limpar dados e redirecionar
   */
  logout(): void {
    this.clearAuth();
    this.router.navigate(['/signin']);
    console.log('🚪 Logout realizado');
  }

  /**
   * 🔄 REFRESH TOKEN - Renovar token automaticamente
   */
  refreshToken(): Observable<boolean> {
    const refreshToken = this.getRefreshToken();
    if (!refreshToken) {
      return new Observable(observer => {
        observer.next(false);
        observer.complete();
      });
    }

    const apiUrl = 'https://prafrota-be-bff-tenant-api.grupopra.tech/auth/refresh';
    
    return new Observable(observer => {
      this.http.post<LoginResponse>(apiUrl, { refresh_token: refreshToken }).subscribe({
        next: (response) => {
          if (response.success && response.data) {
            this.setToken(response.data.token);
            this.setUserData(response.data.user);
            
            this.currentUserSubject.next(response.data.user);
            this.isAuthenticatedSubject.next(true);
            
            observer.next(true);
            observer.complete();
          } else {
            this.clearAuth();
            observer.next(false);
            observer.complete();
          }
        },
        error: () => {
          this.clearAuth();
          observer.next(false);
          observer.complete();
        }
      });
    });
  }

  // 🎯 GETTERS PÚBLICOS

  /**
   * 👤 Obter dados do usuário atual
   */
  getCurrentUser(): AuthUser | null {
    return this.currentUserSubject.value;
  }

  /**
   * 🆔 Obter ID do usuário logado
   */
  getCurrentUserId(): string | null {
    const user = this.getCurrentUser();
    return user ? user.id : null;
  }

  /**
   * 📧 Obter email do usuário logado
   */
  getCurrentUserEmail(): string | null {
    const user = this.getCurrentUser();
    return user ? user.email : null;
  }

  /**
   * 🔐 Obter nível de acesso do usuário
   */
  getCurrentUserAccessLevel(): string | null {
    const user = this.getCurrentUser();
    return user ? user.access_level : null;
  }

  /**
   * 🔑 Verificar se usuário está autenticado
   */
  isAuthenticated(): boolean {
    return this.isAuthenticatedSubject.value;
  }

  /**
   * 🎫 Obter token de acesso
   */
  getToken(): string | null {
    return localStorage.getItem(this.TOKEN_KEY);
  }

  /**
   * 🔄 Obter refresh token
   */
  getRefreshToken(): string | null {
    return localStorage.getItem(this.REFRESH_TOKEN_KEY);
  }

  /**
   * 👥 Verificar se usuário tem permissão específica
   */
  hasPermission(permission: string): boolean {
    const user = this.getCurrentUser();
    if (!user || !user.permissions) return false;
    return user.permissions.includes(permission);
  }

  /**
   * 🔐 Verificar se usuário tem nível de acesso mínimo
   */
  hasMinimumAccessLevel(requiredLevel: string): boolean {
    const user = this.getCurrentUser();
    if (!user) return false;

    const levels = ['viewer', 'operator', 'manager', 'admin'];
    const userLevelIndex = levels.indexOf(user.access_level);
    const requiredLevelIndex = levels.indexOf(requiredLevel);

    return userLevelIndex >= requiredLevelIndex;
  }

  // 🔧 MÉTODOS PRIVADOS

  /**
   * 🔍 Buscar detalhes completos do usuário via API
   */
  private fetchUserDetails(userId: string): Observable<AuthUser> {
    const tenantId = localStorage.getItem('tenant_id');
    const token = this.getToken();
    
    if (!tenantId || !token) {
      return throwError(() => new Error('Token ou Tenant ID não encontrados'));
    }

    const headers = {
      'x-tenant-uuid': tenantId,
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    };
    
    const apiUrl = `https://prafrota-be-bff-tenant-api.grupopra.tech/user/${userId}`;
    
    return this.http.get<any>(apiUrl, { headers }).pipe(
      switchMap(response => {
        console.log('🔍 Resposta da API de detalhes do usuário:', response);
        
        // 🎯 EXTRAIR dados do objeto 'data' da resposta
        const userData = response.data || response;
        
        // 🔄 Se tem photoId, buscar a URL da imagem
        if (userData.photoId) {
          return this.imageUploadService.getImageById(userData.photoId).pipe(
            map(imageResponse => {
              const completeUser: AuthUser = {
                id: userData.id || userId,
                name: userData.name || userData.full_name || userData.email?.split('@')[0],
                email: userData.email,
                access_level: userData.access_level || userData.role || 'user',
                tenant_id: tenantId,
                permissions: userData.permissions || [],
                avatar: imageResponse.data.downloadUrl, // URL real da imagem
                full_name: userData.full_name || userData.name,
                phone: userData.phone || userData.telephone,
                department: userData.department || userData.sector,
                last_login: userData.last_login || userData.last_access || userData.createdAt,
                created_at: userData.created_at || userData.createdAt,
                updated_at: userData.updated_at || userData.updatedAt
              };
              console.log('✅ Dados completos do usuário mapeados (com avatar):', completeUser);
              return completeUser;
            })
          );
        } else {
          // Sem photoId, usar avatar padrão
          const completeUser: AuthUser = {
            id: userData.id || userId,
            name: userData.name || userData.full_name || userData.email?.split('@')[0],
            email: userData.email,
            access_level: userData.access_level || userData.role || 'user',
            tenant_id: tenantId,
            permissions: userData.permissions || [],
            avatar: 'assets/images/avatar.png', // Avatar padrão
            full_name: userData.full_name || userData.name,
            phone: userData.phone || userData.telephone,
            department: userData.department || userData.sector,
            last_login: userData.last_login || userData.last_access || userData.createdAt,
            created_at: userData.created_at || userData.createdAt,
            updated_at: userData.updated_at || userData.updatedAt
          };
          console.log('✅ Dados completos do usuário mapeados (sem avatar):', completeUser);
          return of(completeUser);
        }
      }),
      catchError(error => {
        console.warn('⚠️ Erro ao buscar detalhes do usuário via API:', error);
        
        // Fallback para dados do localStorage
        const cachedUser = this.getUserData();
        if (cachedUser) {
          console.log('🔄 Usando dados em cache como fallback:', cachedUser);
          return of(cachedUser);
        }
        
        return throwError(() => error);
      })
    );
  }

  /**
   * 💾 Salvar token no localStorage
   */
  private setToken(token: string): void {
    localStorage.setItem(this.TOKEN_KEY, token);
  }

  /**
   * 💾 Salvar refresh token no localStorage
   */
  private setRefreshToken(refreshToken: string): void {
    localStorage.setItem(this.REFRESH_TOKEN_KEY, refreshToken);
  }

  /**
   * 💾 Salvar dados do usuário no localStorage
   */
  private setUserData(user: AuthUser): void {
    localStorage.setItem(this.USER_KEY, JSON.stringify(user));
    this.refreshUserData();
  }

  /**
   * 📖 Obter dados do usuário do localStorage
   */
  private getUserData(): AuthUser | null {
    const userData = localStorage.getItem(this.USER_KEY);
    if (userData) {
      try {
        
        return JSON.parse(userData);
      } catch (error) {
        console.error('Erro ao fazer parse dos dados do usuário:', error);
        return null;
      }
    }
    return null;
  }

  /**
   * 🧹 Limpar todos os dados de autenticação
   */
  private clearAuth(): void {
    localStorage.removeItem(this.TOKEN_KEY);
    localStorage.removeItem(this.REFRESH_TOKEN_KEY);
    localStorage.removeItem(this.USER_KEY);
    
    this.currentUserSubject.next(null);
    this.isAuthenticatedSubject.next(false);
  }

  /**
   * 🔄 Atualizar dados do usuário (após edição de perfil)
   */
  updateUserData(updatedUser: Partial<AuthUser>): void {
    const currentUser = this.getCurrentUser();
    if (currentUser) {
      const newUserData = { ...currentUser, ...updatedUser };
      this.setUserData(newUserData);
      this.currentUserSubject.next(newUserData);
      console.log('👤 Dados do usuário atualizados:', newUserData);
    }
  }



  /**
   * 🔄 Forçar atualização dos dados do usuário via API
   */
  refreshUserData(): Observable<AuthUser> {
    const currentUser = this.getCurrentUser();
    if (!currentUser?.id) {
      return throwError(() => new Error('Usuário não encontrado para atualização'));
    }
    
    console.log('🔄 Forçando atualização dos dados do usuário via API...');
    
    return this.fetchUserDetails(currentUser.id).pipe(
      tap(updatedUser => {
        this.setUserData(updatedUser);
        this.currentUserSubject.next(updatedUser);
        console.log('✅ Dados do usuário atualizados via refreshUserData:', updatedUser);
      }),
      catchError(error => {
        console.error('❌ Erro ao atualizar dados do usuário:', error);
        return throwError(() => error);
      })
    );
  }

  /**
   * 🔍 Extrair ID do usuário do token JWT (método auxiliar)
   */
  private extractUserIdFromToken(token: string): string {
    try {
      // Decodificar JWT para extrair informações (sem verificar assinatura)
      const payload = JSON.parse(atob(token.split('.')[1]));
      const userId = payload.sub || payload.userId || payload.id || payload.user?.user_id || payload.user?.id;
      
      if (userId) {
        return userId.toString();
      }
      
      console.warn('⚠️ Nenhum ID encontrado no token, usando fallback');
      return 'user-' + Date.now();
    } catch (error) {
      console.warn('Não foi possível extrair ID do token, usando ID gerado:', error);
      return 'user-' + Date.now();
    }
  }
} 