/**
 * Account Notification Handler
 *
 * Processes Salesforce Account events and creates in-app notifications
 * when eligibility or verification status changes.
 *
 * This is called by the ServicesCdcSubscriber when account
 * events are received. Works alongside Salesforce's email notifications,
 * providing both push (email) and pull (in-app) notification channels.
 */

import { Injectable, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
import { NotificationService } from "./notifications.service.js";
import { extractErrorMessage } from "@bff/core/utils/error.util.js";
import { NOTIFICATION_TYPE, NOTIFICATION_SOURCE } from "@customer-portal/domain/notifications";

export interface AccountEventPayload {
  accountId: string;
  eligibilityStatus?: string | null;
  eligibilityValue?: string | null;
  verificationStatus?: string | null;
  verificationRejectionMessage?: string | null;
}

@Injectable()
export class AccountNotificationHandler {
  constructor(
    private readonly mappingsService: MappingsService,
    private readonly notificationService: NotificationService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  /**
   * Process an account event and create notifications if needed
   */
  async processAccountEvent(payload: AccountEventPayload): Promise<void> {
    try {
      const {
        accountId,
        eligibilityStatus,
        eligibilityValue,
        verificationStatus,
        verificationRejectionMessage,
      } = payload;

      // Find the portal user for this account
      const mapping = await this.mappingsService.findBySfAccountId(accountId);
      if (!mapping?.userId) {
        this.logger.debug("No portal user for account, skipping notification", {
          accountIdTail: accountId.slice(-4),
        });
        return;
      }

      // Process eligibility status change
      if (eligibilityStatus) {
        await this.processEligibilityChange(
          mapping.userId,
          accountId,
          eligibilityStatus,
          eligibilityValue ?? undefined
        );
      }

      // Process verification status change
      if (verificationStatus) {
        await this.processVerificationChange(
          mapping.userId,
          accountId,
          verificationStatus,
          verificationRejectionMessage ?? undefined
        );
      }
    } catch (error) {
      this.logger.error("Error processing account event for notifications", {
        error: extractErrorMessage(error),
        accountIdTail: payload.accountId.slice(-4),
      });
    }
  }

  /**
   * Process eligibility status change
   */
  private async processEligibilityChange(
    userId: string,
    accountId: string,
    status: string,
    eligibilityValue?: string
  ): Promise<void> {
    const normalizedStatus = status.trim().toLowerCase();

    // Only notify on final states, not "pending"
    if (normalizedStatus === "pending" || normalizedStatus === "checking") {
      return;
    }

    const isEligible = normalizedStatus === "eligible" || Boolean(eligibilityValue);
    const notificationType = isEligible
      ? NOTIFICATION_TYPE.ELIGIBILITY_ELIGIBLE
      : NOTIFICATION_TYPE.ELIGIBILITY_INELIGIBLE;

    // Create customized message if we have the eligibility value
    let message: string | undefined;
    if (isEligible && eligibilityValue) {
      message = `We've confirmed ${eligibilityValue} service is available at your address. You can now select a plan and complete your order.`;
    }

    await this.notificationService.createNotification({
      userId,
      type: notificationType,
      message,
      source: NOTIFICATION_SOURCE.SALESFORCE,
      sourceId: accountId,
    });

    this.logger.log("Eligibility notification created", {
      userId,
      type: notificationType,
      accountIdTail: accountId.slice(-4),
    });
  }

  /**
   * Process ID verification status change
   */
  private async processVerificationChange(
    userId: string,
    accountId: string,
    status: string,
    rejectionMessage?: string
  ): Promise<void> {
    const normalizedStatus = status.trim().toLowerCase();

    // Only notify on final states
    if (normalizedStatus !== "verified" && normalizedStatus !== "rejected") {
      return;
    }

    const isVerified = normalizedStatus === "verified";
    const notificationType = isVerified
      ? NOTIFICATION_TYPE.VERIFICATION_VERIFIED
      : NOTIFICATION_TYPE.VERIFICATION_REJECTED;

    // Include rejection reason in message
    let message: string | undefined;
    if (!isVerified && rejectionMessage) {
      message = `We couldn't verify your ID: ${rejectionMessage}. Please resubmit a clearer image.`;
    }

    await this.notificationService.createNotification({
      userId,
      type: notificationType,
      message,
      source: NOTIFICATION_SOURCE.SALESFORCE,
      sourceId: accountId,
    });

    this.logger.log("Verification notification created", {
      userId,
      type: notificationType,
      accountIdTail: accountId.slice(-4),
    });
  }
}
