import { Inject, Injectable } from '@nestjs/common';
import * as admin from 'firebase-admin';
import { FirebaseUserInfo, UserRole } from 'src/models/main.model';

@Injectable()
export class AuthService {
  constructor(@Inject('FIREBASE_ADMIN') private firebaseAdmin: admin.app.App) {}

  /**
   * Set a user's role via Firebase custom claims
   */
  async setUserRole(uid: string, role: UserRole): Promise<void> {
    try {
      // Get the current custom claims
      const user = await this.firebaseAdmin.auth().getUser(uid);
      const currentClaims = user.customClaims || {};

      // Set the new role
      await this.firebaseAdmin.auth().setCustomUserClaims(uid, {
        ...currentClaims,
        role: role,
      });
    } catch (error) {
      console.error('Error setting user role:', error);
      throw error;
    }
  }

  /**
   * Get a user's current role
   */
  async getUserRole(uid: string): Promise<UserRole | null> {
    try {
      const user = await this.firebaseAdmin.auth().getUser(uid);
      const claims = user.customClaims || {};
      return (claims.role as UserRole) || null;
    } catch (error) {
      console.error('Error getting user role:', error);
      throw error;
    }
  }

  /**
   * Get all users with a specific role
   */
  async getUsersByRole(role: UserRole): Promise<admin.auth.UserRecord[]> {
    // Note: Firebase Admin doesn't provide a direct way to query users by custom claims
    // For a production app, you might want to store role information in Firestore as well
    // This is a simple implementation that lists all users and filters them
    try {
      const listUsersResult = await this.firebaseAdmin.auth().listUsers();
      return listUsersResult.users.filter(user => user.customClaims && user.customClaims.role === role);
    } catch (error) {
      console.error('Error getting users by role:', error);
      throw error;
    }
  }

  /**
   * Get all Firebase users with their roles
   * @param maxResults Maximum number of users to return (optional, default 1000)
   * @param pageToken Token for pagination (optional)
   */
  async getAllUsers(maxResults: number = 1000, pageToken?: string): Promise<{ users: FirebaseUserInfo[]; pageToken?: string }> {
    try {
      const listUsersResult = await this.firebaseAdmin.auth().listUsers(maxResults, pageToken);

      const users = listUsersResult.users.map(user => this.mapUserRecord(user));

      return {
        users,
        pageToken: listUsersResult.pageToken,
      };
    } catch (error) {
      console.error('Error getting all users:', error);
      throw error;
    }
  }
  /**
   * Maps a Firebase UserRecord to our FirebaseUserInfo interface
   */
  private mapUserRecord(user: admin.auth.UserRecord): FirebaseUserInfo {
    return {
      uid: user.uid,
      email: user.email || null,
      displayName: user.displayName || null,
      photoURL: user.photoURL || null,
      phoneNumber: user.phoneNumber || null,
      disabled: user.disabled,
      emailVerified: user.emailVerified,
      role: user.customClaims?.role || null,
      creationTime: user.metadata.creationTime,
      lastSignInTime: user.metadata.lastSignInTime,
      // Optionally include other customClaims if needed
      customClaims: user.customClaims,
    };
  }

  /**
   * Set default role for a new user
   */
  async setDefaultRole(uid: string): Promise<void> {
    return this.setUserRole(uid, 'guest');
  }

  /**
   * Verify if a user has a specific role
   */
  async hasRole(uid: string, role: UserRole): Promise<boolean> {
    const userRole = await this.getUserRole(uid);
    return userRole === role;
  }
}
