import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { QuestionnairePartialSubmission } from '../questionnaire-partial-submission/entities/questionnaire-partial-submission.entity';
import { SmsService } from '../sms/sms.service';
import { SendSmsDto } from '../sms/dto/send-sms.dto';
import { ShortLinkService } from '../short-link/short-link.service';
import {
  QUESTIONNAIRE_REMINDER_MESSAGES,
  personalizeQuestionnaireReminderMessage,
  QuestionnaireReminderMessageVariables,
} from './questionnaire-reminder-messages.config';

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

  constructor(
    @InjectRepository(QuestionnairePartialSubmission)
    private readonly partialSubmissionRepository: Repository<QuestionnairePartialSubmission>,
    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}`);
  }

  /**
   * Traite toutes les soumissions partielles et envoie les rappels appropriés
   * @param simulateDate Date optionnelle pour simuler une date spécifique (pour les tests)
   * @returns Statistiques du traitement et liste des messages envoyés
   */
  async processQuestionnaireReminders(simulateDate?: Date): Promise<{
    totalSubmissions: number;
    remindersToSend: number;
    smsSent: number;
    smsFailed: number;
    sentMessages: Array<{
      name: string;
      phone: string;
      category: string;
    }>;
  }> {
    const today = simulateDate || new Date();
    this.logger.log(
      `Starting questionnaire reminder processing${simulateDate ? ` with simulated date: ${today.toISOString()}` : ''}...`,
    );

    try {
      // Récupérer toutes les soumissions non complétées
      const incompleteSubmissions = await this.partialSubmissionRepository.find(
        {
          where: { is_completed: false },
        },
      );

      this.logger.log(
        `Found ${incompleteSubmissions.length} incomplete submissions`,
      );

      const smsList: SendSmsDto[] = [];
      const sentMessages: Array<{
        name: string;
        phone: string;
        category: string;
      }> = [];
      let smsSent = 0;
      let smsFailed = 0;

      for (const submission of incompleteSubmissions) {
        try {
          // Vérifier si la soumission doit recevoir un rappel aujourd'hui
          const shouldSendReminder = this.shouldSendReminder(
            submission.updated_at,
            today,
          );

          if (shouldSendReminder) {
            const sms = await this.prepareReminderSms(submission);
            if (sms) {
              smsList.push(sms);
              
              // Extraire le prénom depuis les données
              const data = submission.data as Record<string, unknown> | undefined;
              const firstName =
                (typeof data?.firstName === 'string'
                  ? data.firstName
                  : typeof data?.first_name === 'string'
                    ? data.first_name
                    : null) || 'Patient';
              
              // Ajouter à la liste des messages envoyés
              sentMessages.push({
                name: firstName,
                phone: submission.phone_number,
                category: `Rappel questionnaire (étape ${submission.current_step})`,
              });
            }
          }
        } catch (error) {
          this.logger.error(
            `Error processing submission ${submission.id}:`,
            error,
          );
        }
      }

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

            smsSent = results.filter(
              (result) => result.status === 'sent',
            ).length;
            smsFailed = results.filter(
              (result) => result.status === 'failed',
            ).length;

            this.logger.log(
              `Questionnaire reminders: ${smsSent} SMS sent successfully, ${smsFailed} failed`,
            );
          } catch (error) {
            this.logger.error('Error sending bulk SMS for reminders:', error);
            smsFailed = smsList.length;
          }
        } else {
          // Mode test : juste logger les messages
          smsSent = smsList.length; // En mode test, on considère que tout serait envoyé
          this.logger.log(
            `[TEST MODE] Would send ${smsList.length} questionnaire reminder SMS:`,
          );
          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] ---`);
          });
        }
      } else {
        this.logger.log('No reminders to send today');
      }

      this.logger.log('Questionnaire reminder processing completed');

      return {
        totalSubmissions: incompleteSubmissions.length,
        remindersToSend: smsList.length,
        smsSent,
        smsFailed,
        sentMessages,
      };
    } catch (error) {
      this.logger.error('Error processing questionnaire reminders:', error);
      throw error;
    }
  }

  /**
   * Vérifie si un rappel doit être envoyé aujourd'hui
   * Les rappels sont envoyés à J+1, J+2, J+7, J+14, J+28 après updated_at
   * @param updatedAt Date de mise à jour de la soumission
   * @param today Date de référence (par défaut la date actuelle)
   */
  private shouldSendReminder(
    updatedAt: Date,
    today: Date = new Date(),
  ): boolean {
    const todayDate = new Date(today);
    todayDate.setHours(0, 0, 0, 0); // Reset time to start of day

    const updatedDate = new Date(updatedAt);
    updatedDate.setHours(0, 0, 0, 0); // Reset time to start of day

    // Calculer la différence en jours
    const diffInDays = Math.round(
      (todayDate.getTime() - updatedDate.getTime()) / (1000 * 60 * 60 * 24),
    );

    // Vérifier si on est à J+1, J+2, J+7, J+14, ou J+28
    return [1, 2, 7, 14, 28].includes(diffInDays);
  }

  /**
   * Prépare le SMS de rappel pour une soumission
   */
  private async prepareReminderSms(
    submission: QuestionnairePartialSubmission,
  ): Promise<SendSmsDto | null> {
    try {
      // Sélectionner le message selon le current_step (1-5)
      const stepKey = this.getStepKey(submission.current_step);
      if (!stepKey) {
        this.logger.warn(
          `No message template found for step ${submission.current_step}`,
        );
        return null;
      }

      const messageTemplate = QUESTIONNAIRE_REMINDER_MESSAGES[stepKey];

      // Extraire le prénom depuis les données
      const data = submission.data as Record<string, unknown> | undefined;
      const firstName =
        (typeof data?.firstName === 'string'
          ? data.firstName
          : typeof data?.first_name === 'string'
            ? data.first_name
            : null) || 'Patient';

      // Construire l'URL du formulaire au format websiteUrl/:centreId/:uuid
      const center = submission.center || '';
      const originalUrl = `${this.websiteUrl}/onboarding/${encodeURIComponent(center)}/${submission.uuid}`;

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

      // Personnaliser le message
      const variables: QuestionnaireReminderMessageVariables = {
        firstName,
        form: shortUrl,
      };

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

      return {
        to: submission.phone_number,
        message: personalizedMessage,
        sender: messageTemplate.sender,
      };
    } catch (error) {
      this.logger.error(
        `Error preparing reminder SMS for submission ${submission.id}:`,
        error,
      );
      return null;
    }
  }

  /**
   * Convertit le current_step en clé de message (step1-step5)
   * Les steps 1-5 correspondent aux messages step1-step5
   * Pour les steps supérieurs, on utilise le dernier message (step5)
   */
  private getStepKey(
    currentStep: number,
  ): keyof typeof QUESTIONNAIRE_REMINDER_MESSAGES | null {
    if (currentStep >= 1 && currentStep <= 5) {
      return `step${currentStep}` as keyof typeof QUESTIONNAIRE_REMINDER_MESSAGES;
    }
    // Pour les steps > 5, utiliser le dernier message
    if (currentStep > 5) {
      return 'step5';
    }
    return null;
  }
}
