// Handles `session-communication-trigger` events (EventBridge → SQS): the scheduled
// Welcome / Program-completion sends. Delegates to SessionCommunicationService.
import { Injectable } from '@nestjs/common';
import { QueueProcessor } from '../services/processor-registry.service';
import {
  QueueMessage,
  QueueProcessingResult,
  SessionCommunicationTriggerQueueMessage,
} from '../interfaces/queue-message.interface';
import { QUEUE_CONSTANTS } from '../constants/queue.constants';
import { classifyQueueError } from '../utils/queue-error.util';
import { AppLoggerService } from 'src/common/services/logger.service';
import { SessionCommunicationService } from 'src/session-communication/session-communication.service';
import { SessionCommunicationPurposeEnum } from 'src/common/enum/session-communication-purpose.enum';

/** Auto-triggered purposes are program-level and system-actored. */
const SYSTEM_ACTOR_USER_ID = 0;
const SCHEDULABLE_PURPOSES: string[] = [
  SessionCommunicationPurposeEnum.WELCOME,
  SessionCommunicationPurposeEnum.PROGRAM_COMPLETION,
];

@Injectable()
export class SessionCommunicationTriggerProcessor implements QueueProcessor {
  constructor(
    private readonly sessionCommunicationService: SessionCommunicationService,
    private readonly logger: AppLoggerService,
  ) {}

  async process(message: QueueMessage): Promise<QueueProcessingResult> {
    const startTime = Date.now();

    if (
      message.queueType !== QUEUE_CONSTANTS.QUEUE_TYPES.EVENT ||
      message.subType !== QUEUE_CONSTANTS.EVENT_TYPES.SESSION_COMMUNICATION_TRIGGER
    ) {
      return this.failure(message, startTime, {
        code: 'INVALID_MESSAGE_TYPE',
        message: `Expected session-communication-trigger message, got: ${message.queueType}/${message.subType}`,
        retryable: false,
      });
    }

    const { data } = message as SessionCommunicationTriggerQueueMessage;
    const { programId, purpose, actorUserId } = data;

    if (!programId || !SCHEDULABLE_PURPOSES.includes(purpose)) {
      return this.failure(message, startTime, {
        code: QUEUE_CONSTANTS.ERROR_TYPES.VALIDATION_ERROR,
        message: `session-communication-trigger message invalid: programId=${programId}, purpose=${purpose}`,
        retryable: false,
      });
    }

    try {
      await this.sessionCommunicationService.triggerProgramCommunication(
        programId,
        purpose as SessionCommunicationPurposeEnum,
        actorUserId ?? SYSTEM_ACTOR_USER_ID,
      );
      this.logger.log(
        `session-communication-trigger processed: programId=${programId}, purpose=${purpose}, ` +
          `attempt=${message.attemptCount || 1}`,
      );
      return {
        success: true,
        messageId: message.messageId || 'unknown',
        queueType: message.queueType,
        processingTimeMs: Date.now() - startTime,
      };
    } catch (error) {
      const classified = classifyQueueError(error);
      this.logger.error(
        `Failed session-communication-trigger: programId=${programId}, purpose=${purpose}`,
        classified.stack ?? '',
        { programId, purpose, error: classified.message, attemptCount: message.attemptCount },
      );
      return this.failure(message, startTime, {
        code: classified.code,
        message: classified.message,
        retryable: classified.retryable,
        stack: classified.stack,
      });
    }
  }

  private failure(
    message: QueueMessage,
    startTime: number,
    error: { code: string; message: string; retryable: boolean; stack?: string },
  ): QueueProcessingResult {
    return {
      success: false,
      messageId: message.messageId || 'unknown',
      queueType: message.queueType,
      processingTimeMs: Date.now() - startTime,
      error,
    };
  }
}
