import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import twilio from 'twilio';
import { SendSmsDto } from './dto/send-sms.dto';

export interface TwilioSmsResponse {
  messageId: string;
  status: string;
}

@Injectable()
export class SmsService {
  private readonly logger = new Logger(SmsService.name);
  private readonly twilioClient: twilio.Twilio | null;
  private readonly messagingServiceSid: string;
  private readonly defaultWebhookUrl: string | undefined;

  constructor(
    private readonly configService: ConfigService,
  ) {
    const accountSid = this.configService.get<string>('TWILIO_ACCOUNT_SID');
    const authToken = this.configService.get<string>('TWILIO_AUTH_TOKEN');
    this.messagingServiceSid = this.configService.get<string>('TWILIO_MESSAGING_SERVICE_SID') || '';
    this.defaultWebhookUrl = this.configService.get<string>('TWILIO_WEBHOOK_URL');

    if (!accountSid || !authToken) {
      this.logger.warn('TWILIO_ACCOUNT_SID or TWILIO_AUTH_TOKEN is not configured');
      this.twilioClient = null;
    } else {
      this.twilioClient = twilio(accountSid, authToken);
    }

    if (!this.messagingServiceSid) {
      this.logger.warn('TWILIO_MESSAGING_SERVICE_SID is not configured');
    }
  }

  async sendSms(sendSmsDto: SendSmsDto): Promise<TwilioSmsResponse> {
    if (!this.twilioClient) {
      throw new Error('Twilio client is not configured. Please set TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN');
    }

    if (!this.messagingServiceSid) {
      throw new Error('TWILIO_MESSAGING_SERVICE_SID is not configured');
    }

    try {
      // Utiliser le webUrl fourni dans le DTO, sinon celui de la config, sinon undefined
      const statusCallback = sendSmsDto.webUrl || this.defaultWebhookUrl;

      const messageOptions: {
        messagingServiceSid: string;
        to: string;
        body: string;
        statusCallback?: string;
      } = {
        messagingServiceSid: this.messagingServiceSid,
        to: sendSmsDto.to,
        body: sendSmsDto.message,
      };

      // Ajouter statusCallback seulement s'il est défini
      if (statusCallback) {
        messageOptions.statusCallback = statusCallback;
        this.logger.log(`Sending SMS to ${sendSmsDto.to} with webhook URL: ${statusCallback}`);
      } else {
        this.logger.log(`Sending SMS to ${sendSmsDto.to} (no webhook URL)`);
      }

      const message = await this.twilioClient.messages.create(messageOptions);

      this.logger.log(`SMS sent successfully to ${sendSmsDto.to}. Message SID: ${message.sid}`);

      const messageId = message.sid || 'unknown';

      return {
        messageId,
        status: message.status === 'queued' || message.status === 'sent' ? 'sent' : message.status,
      };
    } catch (error) {
      const twilioError = error as any;
      this.logger.error(
        `Failed to send SMS to ${sendSmsDto.to}:`,
        twilioError.message || twilioError,
      );
      throw new Error(
        `Failed to send SMS: ${twilioError.message || 'Unknown error'}`,
      );
    }
  }

  async sendBulkSms(smsList: SendSmsDto[]): Promise<TwilioSmsResponse[]> {
    const results: TwilioSmsResponse[] = [];

    for (const sms of smsList) {
      try {
        const result = await this.sendSms(sms);
        results.push(result);
      } catch (error) {
        const twilioError = error as any;
        this.logger.error(`Failed to send SMS to ${sms.to}:`, twilioError.message);
        results.push({
          messageId: 'failed',
          status: 'failed',
        });
      }
    }

    return results;
  }
}
