import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { SmsService } from '../sms/sms.service';
import { SendSmsDto } from '../sms/dto/send-sms.dto';
import { ShortLinkService } from '../short-link/short-link.service';
import { DateIvtWithQuestionnaire, DateIvtGroups } from './cron.service';
import {
  MESSAGE_CONFIG,
  personalizeMessage,
  MessageVariables,
} from './messages.config';

@Injectable()
export class MessageService {
  private readonly logger = new Logger(MessageService.name);
  private readonly enableRealSms: boolean;
  private readonly websiteUrl: string;
  private readonly apiUrl: string;

  constructor(
    private readonly smsService: SmsService,
    private readonly shortLinkService: ShortLinkService,
    private readonly configService: ConfigService,
  ) {
    this.enableRealSms =
      this.configService.get<string>('ENABLE_REAL_SMS') === 'true';
    this.websiteUrl =
      this.configService.get<string>('WEBSITE_URL') || 'http://localhost:5173';
    this.apiUrl =
      this.configService.get<string>('API_URL') ||
      this.configService.get<string>('SERVER_URL') ||
      'http://localhost:3000';
    this.logger.log(
      `SMS sending mode: ${this.enableRealSms ? 'REAL SMS' : 'TEST MODE (logs only)'}`,
    );
    this.logger.log(`Website URL: ${this.websiteUrl}`);
    this.logger.log(`API URL: ${this.apiUrl}`);
  }

  /**
   * Envoie des SMS pour tous les groupes de patients
   * @returns Liste des messages envoyés avec nom, téléphone et catégorie
   */
  async sendMessagesForAllGroups(groups: DateIvtGroups): Promise<Array<{
    name: string;
    phone: string;
    category: string;
  }>> {
    this.logger.log('Starting SMS sending for all groups...');

    const allSentMessages: Array<{
      name: string;
      phone: string;
      category: string;
    }> = [];

    try {
      // Envoyer les messages pour chaque catégorie
      const inTwoDaysMessages = await this.sendMessagesForGroup(groups.inTwoDays, 'inTwoDays');
      allSentMessages.push(...inTwoDaysMessages);
      
      const passedOneDayMessages = await this.sendMessagesForGroup(groups.passedOneDay, 'passedOneDay');
      allSentMessages.push(...passedOneDayMessages);
      
      // Temporairement désactivé : passedBetweenTwoAndSixDays
      // const passedBetweenTwoAndSixDaysMessages = await this.sendMessagesForGroup(
      //   groups.passedBetweenTwoAndSixDays,
      //   'passedBetweenTwoAndSixDays',
      // );
      // allSentMessages.push(...passedBetweenTwoAndSixDaysMessages);
      
      // Temporairement désactivé : passedSevenDays
      // const passedSevenDaysMessages = await this.sendMessagesForGroup(
      //   groups.passedSevenDays,
      //   'passedSevenDays',
      // );
      // allSentMessages.push(...passedSevenDaysMessages);

      // Envoyer les messages passedMoreThanSevenDays seulement le lundi
      // Utiliser le fuseau horaire Europe/Paris comme le cron job
      const today = new Date();
      // Obtenir le jour de la semaine en Europe/Paris
      const dayNameInParis = today.toLocaleString('fr-FR', {
        timeZone: 'Europe/Paris',
        weekday: 'long',
      });
      // Vérifier si c'est lundi (case-insensitive pour éviter les problèmes d'accents)
      const isMonday = dayNameInParis.toLowerCase().startsWith('lundi');

      if (isMonday) {
        const passedMoreThanSevenDaysMessages = await this.sendMessagesForGroup(
          groups.passedMoreThanSevenDays,
          'passedMoreThanSevenDays',
        );
        allSentMessages.push(...passedMoreThanSevenDaysMessages);
        this.logger.log(
          `Monday detected (${dayNameInParis} in Europe/Paris): sending messages for passedMoreThanSevenDays group`,
        );
      } else {
        this.logger.log(
          `Not Monday (current day: ${dayNameInParis} in Europe/Paris): skipping passedMoreThanSevenDays group. ${groups.passedMoreThanSevenDays.length} records will be processed next Monday.`,
        );
      }

      this.logger.log('All SMS messages sent successfully');
      return allSentMessages;
    } catch (error) {
      this.logger.error('Error sending SMS messages:', error);
      throw error;
    }
  }

  /**
   * Mappe les types de groupes en noms de catégories français
   */
  private getCategoryName(groupType: keyof DateIvtGroups): string {
    const categoryMap: Record<keyof DateIvtGroups, string> = {
      inTwoDays: 'Rappel J-2 (injection dans 2 jours)',
      passedOneDay: 'Confirmation J+1 (injection hier)',
      passedBetweenTwoAndSixDays: 'Rappel J+2 à J+6',
      passedSevenDays: 'Rappel J+7',
      passedMoreThanSevenDays: 'Rappel J+7+ (date manquante)',
    };
    return categoryMap[groupType] || groupType;
  }

  /**
   * Envoie des SMS pour un groupe spécifique de patients
   * @returns Liste des messages envoyés avec nom, téléphone et catégorie
   */
  private async sendMessagesForGroup(
    patients: DateIvtWithQuestionnaire[],
    groupType: keyof DateIvtGroups,
  ): Promise<Array<{
    name: string;
    phone: string;
    category: string;
  }>> {
    const sentMessages: Array<{
      name: string;
      phone: string;
      category: string;
    }> = [];

    if (patients.length === 0) {
      this.logger.log(
        `No patients in group ${groupType}, skipping SMS sending`,
      );
      return sentMessages;
    }

    this.logger.log(
      `Sending SMS to ${patients.length} patients in group ${groupType}`,
    );

    const messageTemplate = MESSAGE_CONFIG[groupType];
    const smsList: SendSmsDto[] = [];
    const categoryName = this.getCategoryName(groupType);

    for (const patient of patients) {
      try {
        // Construire l'URL du formulaire et la raccourcir
        const formUrl = await this.buildAndShortenFormUrl(patient, groupType);

        // Inclure medication seulement si ce n'est pas "Autre" ou "Je ne sais pas"
        const medication = patient.questionnaire?.medication;
        const medicationValue = 
          medication && 
          medication !== 'Autre' && 
          medication !== 'Je ne sais pas'
            ? medication
            : undefined;

        const variables: MessageVariables = {
          patientName: patient.first_name || 'Patient',
          injectionDate: new Date(
            patient.next_injection_date,
          ).toLocaleDateString('fr-FR'),
          phoneNumber: patient.phone_number,
          medication: medicationValue,
          formLink: formUrl,
        };

        const personalizedMessage = personalizeMessage(
          messageTemplate.message,
          variables,
        );

        smsList.push({
          to: patient.phone_number,
          message: personalizedMessage,
          sender: messageTemplate.sender,
        });

        // Ajouter à la liste des messages envoyés
        sentMessages.push({
          name: patient.first_name || 'Patient',
          phone: patient.phone_number,
          category: categoryName,
        });

        this.logger.log(
          `Prepared SMS for patient ${patient.phone_number} in group ${groupType}`,
        );
      } catch (error) {
        this.logger.error(
          `Error preparing SMS for patient ${patient.phone_number}:`,
          error,
        );
      }
    }

    // Envoyer tous les SMS du groupe
    if (smsList.length > 0) {
      if (this.enableRealSms) {
        try {
          const results = await this.smsService.sendBulkSms(smsList);

          const successCount = results.filter(
            (result) => result.status === 'sent',
          ).length;
          const failureCount = results.filter(
            (result) => result.status === 'failed',
          ).length;

      this.logger.log(
        `Group ${groupType}: ${successCount} SMS sent successfully, ${failureCount} failed`,
      );
        } catch (error) {
          this.logger.error(
            `Error sending bulk SMS for group ${groupType}:`,
            error,
          );
        }
      } else {
        // Mode test : juste logger les messages
        this.logger.log(
          `[TEST MODE] Would send ${smsList.length} SMS for group ${groupType}:`,
        );
        smsList.forEach((sms, index) => {
          this.logger.log(`[TEST MODE] SMS ${index + 1} to ${sms.to}:`);
          this.logger.log(`[TEST MODE] Message: ${sms.message}`);
          this.logger.log(`[TEST MODE] Sender: ${sms.sender}`);
          this.logger.log(`[TEST MODE] ---`);
        });
      }
    }

    return sentMessages;
  }

  /**
   * Envoie un SMS de test pour un patient spécifique
   */
  async sendTestMessage(
    patient: DateIvtWithQuestionnaire,
    groupType: keyof DateIvtGroups,
  ): Promise<void> {
    this.logger.log(
      `Sending test SMS for patient ${patient.phone_number} in group ${groupType}`,
    );

    try {
      const messageTemplate = MESSAGE_CONFIG[groupType];
      // Construire l'URL du formulaire et la raccourcir
      const formUrl = await this.buildAndShortenFormUrl(patient, groupType);

      // Inclure medication seulement si ce n'est pas "Autre" ou "Je ne sais pas"
      const medication = patient.questionnaire?.medication;
      const medicationValue = 
        medication && 
        medication !== 'Autre' && 
        medication !== 'Je ne sais pas'
          ? medication
          : undefined;

      const variables: MessageVariables = {
        patientName: patient.first_name || 'Patient',
        injectionDate: new Date(patient.next_injection_date).toLocaleDateString(
          'fr-FR',
        ),
        phoneNumber: patient.phone_number,
        medication: medicationValue,
        formLink: formUrl,
      };

      const personalizedMessage = personalizeMessage(
        messageTemplate.message,
        variables,
      );

      if (this.enableRealSms) {
        const result = await this.smsService.sendSms({
          to: patient.phone_number,
          message: personalizedMessage,
          sender: messageTemplate.sender,
        });

        this.logger.log(
          `Test SMS sent successfully to ${patient.phone_number}: ${result.messageId}`,
        );
      } else {
        // Mode test : juste logger le message
        this.logger.log(
          `[TEST MODE] Would send SMS to ${patient.phone_number}:`,
        );
        this.logger.log(`[TEST MODE] Message: ${personalizedMessage}`);
        this.logger.log(`[TEST MODE] Sender: ${messageTemplate.sender}`);
      }
    } catch (error) {
      this.logger.error(
        `Error sending test SMS to ${patient.phone_number}:`,
        error,
      );
      throw error;
    }
  }

  /**
   * Construit l'URL du formulaire approprié et la raccourcit
   * Pour les rappels d'injection, utilise le formulaire post-injection
   * Pour passedMoreThanSevenDays, utilise le formulaire date-ivt
   * @param patient Le patient avec ses données
   * @param groupType Le type de groupe pour déterminer quel formulaire utiliser
   * @returns L'URL courte du formulaire
   */
  private async buildAndShortenFormUrl(
    patient: DateIvtWithQuestionnaire,
    groupType: keyof DateIvtGroups,
  ): Promise<string> {
    try {
      // Récupérer le centre depuis le questionnaire
      const center = patient.questionnaire?.center || '';
      const centerId = encodeURIComponent(center);

      let originalUrl: string;

      if (groupType === 'passedMoreThanSevenDays') {
        // Pour ce groupe, utiliser le formulaire date-ivt avec questionnaireUuid
        const questionnaireUuid = patient.questionnaire?.uuid;
        if (!questionnaireUuid) {
          throw new Error(
            `Questionnaire UUID not found for patient ${patient.phone_number}`,
          );
        }
        originalUrl = `${this.websiteUrl}/date-ivt/${centerId}/${questionnaireUuid}`;
      } else {
        // Pour les autres groupes, utiliser le formulaire post-injection avec dateIvt uuid
        originalUrl = `${this.websiteUrl}/post-injection/${centerId}/${patient.uuid}`;
      }

      // Créer un lien court
      const shortCode = await this.shortLinkService.createShortLink(originalUrl);
      const shortUrl = `${this.apiUrl}/s/${shortCode}`;

      return shortUrl;
    } catch (error) {
      this.logger.error(
        `Error building form URL for patient ${patient.phone_number}:`,
        error,
      );
      // En cas d'erreur, retourner un lien par défaut
      return 'https://example.com/form';
    }
  }
}
