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

// Interfaces alignées avec le contrôleur MerchantUsersController
export interface MerchantUserResponse {
  id: string;
  username: string;
  email: string;
  firstName: string;
  lastName: string;
  role: UserRole.DCB_PARTNER_ADMIN | UserRole.DCB_PARTNER_MANAGER | UserRole.DCB_PARTNER_SUPPORT;
  enabled: boolean;
  emailVerified: boolean;
  merchantPartnerId: string;
  createdBy: string;
  createdByUsername: string;
  createdTimestamp: number;
  lastLogin?: number;
  userType: 'MERCHANT';
}

export interface CreateMerchantUserDto {
  username: string;
  email: string;
  firstName: string;
  lastName: string;
  password: string;
  role: UserRole.DCB_PARTNER_ADMIN | UserRole.DCB_PARTNER_MANAGER | UserRole.DCB_PARTNER_SUPPORT;
  enabled?: boolean;
  emailVerified?: boolean;
  merchantPartnerId: string;
}

export interface UpdateMerchantUserDto {
  firstName?: string;
  lastName?: string;
  email?: string;
  enabled?: boolean;
}

export interface ResetPasswordDto {
  newPassword: string;
  temporary?: boolean;
}

export interface MerchantPartnerStatsResponse {
  totalAdmins: number;
  totalManagers: number;
  totalSupport: number;
  totalUsers: number;
  activeUsers: number;
  inactiveUsers: number;
}

export interface AvailableRole {
  value: UserRole;
  label: string;
  description: string;
  allowedForCreation: boolean;
}

export interface AvailableRolesResponse {
  roles: AvailableRole[];
}

export interface SearchMerchantUsersParams {
  query?: string;
  role?: UserRole.DCB_PARTNER_ADMIN | UserRole.DCB_PARTNER_MANAGER | UserRole.DCB_PARTNER_SUPPORT;
  enabled?: boolean;
}

export enum UserRole {
  DCB_PARTNER_ADMIN = 'DCB_PARTNER_ADMIN',
  DCB_PARTNER_MANAGER = 'DCB_PARTNER_MANAGER',
  DCB_PARTNER_SUPPORT = 'DCB_PARTNER_SUPPORT'
}

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

  // === RÉCUPÉRATION D'UTILISATEURS ===

  /**
   * Récupère les utilisateurs marchands de l'utilisateur courant
   */
  getMyMerchantUsers(): Observable<MerchantUserResponse[]> {
    return this.http.get<MerchantUserResponse[]>(this.apiUrl).pipe(
      catchError(error => {
        console.error('Error loading my merchant users:', error);
        return throwError(() => error);
      })
    );
  }

  /**
   * Récupère les utilisateurs marchands par ID de partenaire
   */
  getMerchantUsersByPartner(partnerId: string): Observable<MerchantUserResponse[]> {
    return this.http.get<MerchantUserResponse[]>(`${this.apiUrl}/partner/${partnerId}`).pipe(
      catchError(error => {
        console.error(`Error loading merchant users for partner ${partnerId}:`, error);
        return throwError(() => error);
      })
    );
  }

  /**
   * Récupère un utilisateur marchand par ID
   */
  getMerchantUserById(id: string): Observable<MerchantUserResponse> {
    return this.http.get<MerchantUserResponse>(`${this.apiUrl}/${id}`).pipe(
      catchError(error => {
        console.error(`Error loading merchant user ${id}:`, error);
        return throwError(() => error);
      })
    );
  }

  // === CRÉATION D'UTILISATEURS ===

  /**
   * Crée un nouvel utilisateur marchand
   */
  createMerchantUser(createUserDto: CreateMerchantUserDto): Observable<MerchantUserResponse> {
    // Validation
    if (!createUserDto.username?.trim()) {
      return throwError(() => 'Username is required and cannot be empty');
    }

    if (!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');
    }

    if (!createUserDto.role) {
      return throwError(() => 'Role is required');
    }

    if (!createUserDto.merchantPartnerId?.trim()) {
      return throwError(() => 'Merchant Partner ID is required');
    }

    // 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,
      role: createUserDto.role,
      merchantPartnerId: createUserDto.merchantPartnerId.trim(),
      enabled: createUserDto.enabled !== undefined ? createUserDto.enabled : true,
      emailVerified: createUserDto.emailVerified !== undefined ? createUserDto.emailVerified : false,
    };

    return this.http.post<MerchantUserResponse>(this.apiUrl, payload).pipe(
      catchError(error => {
        console.error('Error creating merchant user:', error);
        return throwError(() => error);
      })
    );
  }

  // === MISE À JOUR D'UTILISATEURS ===

  /**
   * Met à jour un utilisateur marchand
   */
  updateMerchantUser(id: string, updateUserDto: UpdateMerchantUserDto): Observable<MerchantUserResponse> {
    return this.http.put<MerchantUserResponse>(`${this.apiUrl}/${id}`, updateUserDto).pipe(
      catchError(error => {
        console.error(`Error updating merchant user ${id}:`, error);
        return throwError(() => error);
      })
    );
  }

  // === SUPPRESSION D'UTILISATEURS ===

  /**
   * Supprime un utilisateur marchand
   */
  deleteMerchantUser(id: string): Observable<{ message: string }> {
    return this.http.delete<{ message: string }>(`${this.apiUrl}/${id}`).pipe(
      catchError(error => {
        console.error(`Error deleting merchant user ${id}:`, error);
        return throwError(() => error);
      })
    );
  }

  // === GESTION DES MOTS DE PASSE ===

  /**
   * Réinitialise le mot de passe d'un utilisateur marchand
   */
  resetMerchantUserPassword(id: string, resetPasswordDto: ResetPasswordDto): Observable<{ message: string }> {
    return this.http.post<{ message: string }>(
      `${this.apiUrl}/${id}/reset-password`,
      resetPasswordDto
    ).pipe(
      catchError(error => {
        console.error(`Error resetting password for merchant user ${id}:`, error);
        return throwError(() => error);
      })
    );
  }

  // === STATISTIQUES ET RAPPORTS ===

  /**
   * Récupère les statistiques des utilisateurs marchands
   */
  getMerchantUsersStats(): Observable<MerchantPartnerStatsResponse> {
    return this.http.get<MerchantPartnerStatsResponse>(`${this.apiUrl}/stats/overview`).pipe(
      catchError(error => {
        console.error('Error loading merchant users stats:', error);
        return throwError(() => error);
      })
    );
  }

  // === RECHERCHE ET FILTRES ===

  /**
   * Recherche des utilisateurs marchands avec filtres
   */
  searchMerchantUsers(params: SearchMerchantUsersParams): Observable<MerchantUserResponse[]> {
    let httpParams = new HttpParams();

    if (params.query) {
      httpParams = httpParams.set('query', params.query);
    }

    if (params.role) {
      httpParams = httpParams.set('role', params.role);
    }

    if (params.enabled !== undefined) {
      httpParams = httpParams.set('enabled', params.enabled.toString());
    }

    return this.http.get<MerchantUserResponse[]>(`${this.apiUrl}/search`, { params: httpParams }).pipe(
      catchError(error => {
        console.error('Error searching merchant users:', error);
        return throwError(() => error);
      })
    );
  }

  // === GESTION DES RÔLES ===

  /**
   * Récupère les rôles marchands disponibles
   */
  getAvailableMerchantRoles(): Observable<AvailableRolesResponse> {
    return this.http.get<AvailableRolesResponse>(`${this.apiUrl}/roles/available`).pipe(
      catchError(error => {
        console.error('Error loading available merchant roles:', error);
        // Fallback en cas d'erreur
        return of({
          roles: [
            {
              value: UserRole.DCB_PARTNER_ADMIN,
              label: 'Partner Admin',
              description: 'Full administrative access within the merchant partner',
              allowedForCreation: true
            },
            {
              value: UserRole.DCB_PARTNER_MANAGER,
              label: 'Partner Manager',
              description: 'Manager access with limited administrative capabilities',
              allowedForCreation: true
            },
            {
              value: UserRole.DCB_PARTNER_SUPPORT,
              label: 'Partner Support',
              description: 'Support role with read-only and basic operational access',
              allowedForCreation: true
            }
          ]
        });
      })
    );
  }

  // === GESTION DU STATUT ===

  /**
   * Active un utilisateur marchand
   */
  enableMerchantUser(id: string): Observable<MerchantUserResponse> {
    return this.updateMerchantUser(id, { enabled: true });
  }

  /**
   * Désactive un utilisateur marchand
   */
  disableMerchantUser(id: string): Observable<MerchantUserResponse> {
    return this.updateMerchantUser(id, { enabled: false });
  }

  // === UTILITAIRES ===

  /**
   * Vérifie si un nom d'utilisateur existe parmi les utilisateurs marchands
   */
  merchantUserExists(username: string): Observable<{ exists: boolean }> {
    return this.getMyMerchantUsers().pipe(
      map(users => ({
        exists: users.some(user => user.username === username)
      })),
      catchError(error => {
        console.error('Error checking if merchant user exists:', error);
        return of({ exists: false });
      })
    );
  }

  /**
   * Récupère les utilisateurs par rôle spécifique
   */
  getMerchantUsersByRole(role: UserRole.DCB_PARTNER_ADMIN | UserRole.DCB_PARTNER_MANAGER | UserRole.DCB_PARTNER_SUPPORT): Observable<MerchantUserResponse[]> {
    return this.searchMerchantUsers({ role });
  }

  /**
   * Récupère uniquement les utilisateurs actifs
   */
  getActiveMerchantUsers(): Observable<MerchantUserResponse[]> {
    return this.searchMerchantUsers({ enabled: true });
  }

  /**
   * Récupère uniquement les utilisateurs inactifs
   */
  getInactiveMerchantUsers(): Observable<MerchantUserResponse[]> {
    return this.searchMerchantUsers({ enabled: false });
  }
}