import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '@environments/environment';
import { Observable, map, catchError, throwError } from 'rxjs';
import { of } from 'rxjs';

import {
  UserResponse,
  CreateUserDto,
  UpdateUserDto,
  ResetPasswordDto,
  PaginatedUserResponse,
  ClientRole
} from '../models/user';

@Injectable({ providedIn: 'root' })
export class UsersService {
  private http = inject(HttpClient);
  private apiUrl = `${environment.apiUrl}/users`;

  // === CRUD COMPLET ===
  createUser(createUserDto: CreateUserDto): Observable<UserResponse> {
    // Validation
    if (!createUserDto.username || createUserDto.username.trim() === '') {
      return throwError(() => 'Username is required and cannot be empty');
    }

    if (!createUserDto.email || createUserDto.email.trim() === '') {
      return throwError(() => 'Email is required and cannot be empty');
    }

    if (!createUserDto.password || createUserDto.password.length < 8) {
      return throwError(() => 'Password must be at least 8 characters');
    }

    // Nettoyage des données
    const payload = {
      username: createUserDto.username.trim(),
      email: createUserDto.email.trim(),
      firstName: (createUserDto.firstName || '').trim(),
      lastName: (createUserDto.lastName || '').trim(),
      password: createUserDto.password,
      enabled: createUserDto.enabled !== undefined ? createUserDto.enabled : true,
      emailVerified: createUserDto.emailVerified !== undefined ? createUserDto.emailVerified : false,
      clientRoles: createUserDto.clientRoles || []
    };

    return this.http.post<UserResponse>(`${this.apiUrl}`, payload).pipe(
      catchError(error => throwError(() => error))
    );
  }

  // READ - Obtenir tous les utilisateurs
  findAllUsers(): Observable<PaginatedUserResponse> {
    return this.http.get<{
      users: any[];
      total: number;
      page: number;
      limit: number;
      totalPages: number;
    }>(`${this.apiUrl}`).pipe(
      map(response => {
        const users = response.users.map(user => new UserResponse(user));
        return new PaginatedUserResponse(users, response.total, response.page, response.limit);
      }),
      catchError(error => {
        console.error('Error loading users:', error);
        return of(new PaginatedUserResponse([], 0, 1, 10));
      })
    );
  }

  // READ - Obtenir un utilisateur par ID
  getUserById(id: string): Observable<UserResponse> {
    return this.http.get<any>(`${this.apiUrl}/${id}`).pipe(
      map(response => new UserResponse(response))
    );
  }

  // READ - Obtenir le profil de l'utilisateur connecté
  getCurrentUserProfile(): Observable<UserResponse> {
    return this.http.get<any>(`${this.apiUrl}/profile/me`).pipe(
      map(response => new UserResponse(response))
    );
  }

  // UPDATE - Mettre à jour un utilisateur
  updateUser(id: string, updateUserDto: UpdateUserDto): Observable<UserResponse> {
    return this.http.put<any>(`${this.apiUrl}/${id}`, updateUserDto).pipe(
      map(response => new UserResponse(response))
    );
  }

  // UPDATE - Mettre à jour le profil de l'utilisateur connecté
  updateCurrentUserProfile(updateUserDto: UpdateUserDto): Observable<UserResponse> {
    return this.http.put<any>(`${this.apiUrl}/profile/me`, updateUserDto).pipe(
      map(response => new UserResponse(response))
    );
  }

  // DELETE - Supprimer un utilisateur
  deleteUser(id: string): Observable<{ message: string }> {
    return this.http.delete<{ message: string }>(`${this.apiUrl}/${id}`);
  }

  // === GESTION DES MOTS DE PASSE ===
  resetPassword(resetPasswordDto: ResetPasswordDto): Observable<{ message: string }> {
    return this.http.put<{ message: string }>(
      `${this.apiUrl}/${resetPasswordDto.userId}/password`, 
      resetPasswordDto
    );
  }

  // === GESTION DU STATUT ===
  enableUser(id: string): Observable<{ message: string }> {
    return this.http.put<{ message: string }>(`${this.apiUrl}/${id}/enable`, {});
  }

  disableUser(id: string): Observable<{ message: string }> {
    return this.http.put<{ message: string }>(`${this.apiUrl}/${id}/disable`, {});
  }

  // === RECHERCHE ET VÉRIFICATION ===
  userExists(username: string): Observable<{ exists: boolean }> {
    return this.http.get<{ exists: boolean }>(`${this.apiUrl}/check/${username}`);
  }

  findUserByUsername(username: string): Observable<UserResponse[]> {
    return this.http.get<any[]>(`${this.apiUrl}/search/username/${username}`).pipe(
      map(users => users.map(user => new UserResponse(user)))
    );
  }

  findUserByEmail(email: string): Observable<UserResponse[]> {
    return this.http.get<any[]>(`${this.apiUrl}/search/email/${email}`).pipe(
      map(users => users.map(user => new UserResponse(user)))
    );
  }

  // === GESTION DES RÔLES ===
  getUserClientRoles(id: string): Observable<{ roles: string[] }> {
    return this.http.get<{ roles: string[] }>(`${this.apiUrl}/${id}/roles`);
  }

  assignClientRoles(userId: string, roles: ClientRole[]): Observable<{ message: string }> {
    return this.http.put<{ message: string }>(`${this.apiUrl}/${userId}/roles`, { roles });
  }

  // === SESSIONS ET TOKENS ===
  getUserSessions(userId: string): Observable<any[]> {
    return this.http.get<any[]>(`${this.apiUrl}/${userId}/sessions`);
  }

  logoutUser(userId: string): Observable<{ message: string }> {
    return this.http.post<{ message: string }>(`${this.apiUrl}/${userId}/logout`, {});
  }

  // === STATISTIQUES ===
  getUserStats(): Observable<{
    total: number;
    enabled: number;
    disabled: number;
    emailVerified: number;
    emailNotVerified: number;
  }> {
    return this.http.get<any>(`${this.apiUrl}/stats`);
  }
}