import { Injectable, Logger, HttpException, HttpStatus } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as admin from 'firebase-admin';

export interface PushNotificationPayload {
  title: string;
  body: string;
  data?: Record<string, any>;
  token?: string;
  tokens?: string[];
}

export interface PushNotificationResponse {
  success: boolean;
  messageId?: string;
  error?: string;
}

@Injectable()
export class PushNotificationService {
  private readonly logger = new Logger(PushNotificationService.name);
  private firebaseApp: admin.app.App | null = null;

  constructor(private readonly configService: ConfigService) {
    this.initializeFirebase();
  }

  private initializeFirebase() {
    try {
      const firebaseConfig = this.configService.get<string>('FIREBASE_SERVICE_ACCOUNT');

      if (!firebaseConfig) {
        this.logger.warn('Firebase service account not configured. Push notifications will be disabled.');
        return;
      }

      // Parse the service account JSON
      const serviceAccount = JSON.parse(firebaseConfig);

      if (!this.firebaseApp) {
        this.firebaseApp = admin.initializeApp({
          credential: admin.credential.cert(serviceAccount),
        });
        this.logger.log('Firebase initialized successfully');
      }
    } catch (error) {
      this.logger.error('Failed to initialize Firebase:', error);
      this.logger.warn('Push notifications will be disabled');
    }
  }

  async sendToToken(payload: PushNotificationPayload): Promise<PushNotificationResponse> {
    if (!this.firebaseApp || !payload.token) {
      throw new HttpException(
        'Push notification service not configured or token missing',
        HttpStatus.SERVICE_UNAVAILABLE,
      );
    }

    try {
      const message: admin.messaging.Message = {
        notification: {
          title: payload.title,
          body: payload.body,
        },
        data: this.convertDataToString(payload.data || {}),
        token: payload.token,
        android: {
          priority: 'high',
        },
        apns: {
          headers: {
            'apns-priority': '10',
          },
        },
      };

      const response = await admin.messaging().send(message);
      this.logger.log(`Push notification sent successfully: ${response}`);

      return {
        success: true,
        messageId: response,
      };
    } catch (error) {
      this.logger.error(`Failed to send push notification: ${error}`);
      return {
        success: false,
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  async sendToMultipleTokens(payload: PushNotificationPayload): Promise<PushNotificationResponse> {
    if (!this.firebaseApp || !payload.tokens || payload.tokens.length === 0) {
      throw new HttpException(
        'Push notification service not configured or tokens missing',
        HttpStatus.SERVICE_UNAVAILABLE,
      );
    }

    try {
      const message: admin.messaging.MulticastMessage = {
        notification: {
          title: payload.title,
          body: payload.body,
        },
        data: this.convertDataToString(payload.data || {}),
        tokens: payload.tokens,
        android: {
          priority: 'high',
        },
        apns: {
          headers: {
            'apns-priority': '10',
          },
        },
      };

      const response = await admin.messaging().sendEachForMulticast(message);
      this.logger.log(`Push notifications sent: ${response.successCount} successful, ${response.failureCount} failed`);

      return {
        success: response.successCount > 0,
        messageId: response.responses[0]?.messageId,
        error: response.failureCount > 0 ? `${response.failureCount} notifications failed` : undefined,
      };
    } catch (error) {
      this.logger.error(`Failed to send push notifications: ${error}`);
      return {
        success: false,
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  private convertDataToString(data: Record<string, any>): Record<string, string> {
    const result: Record<string, string> = {};
    for (const [key, value] of Object.entries(data)) {
      result[key] = typeof value === 'string' ? value : JSON.stringify(value);
    }
    return result;
  }

  isConfigured(): boolean {
    return this.firebaseApp !== null;
  }
}
