import { Payer as CrmPayer } from '@isa/crm/data-access';
import { Payer } from '../schemas';

/**
 * Adapter for converting CRM-api payer responses to checkout-api format.
 *
 * Handles:
 * - Filtering CRM-specific fields (agentComment, deactivationComment, etc.)
 * - Entity reference creation (reference.id, source)
 * - Nested object copying (communicationDetails, organisation, address)
 */
export class PayerAdapter {
  private static readonly ADAPTER_NAME = 'PayerAdapter';

  /**
   * Converts CRM-api payer to checkout-api Payer.
   *
   * @remarks
   * Maps payer information from the CRM domain to the checkout domain's
   * payer representation. CRM-specific fields like agentComment, deactivationComment,
   * defaultPaymentPeriod, isGuestAccount, payerGroup, paymentTypes,
   * standardInvoiceText, statusChangeComment, and statusComment are filtered out.
   *
   * Nested objects (communicationDetails, organisation, address) are shallow-copied
   * to prevent unintended mutations.
   *
   * @param crmPayer - Raw payer from CRM service (optional)
   * @returns Payer compatible with checkout-api, or undefined if payer is not provided
   *
   * @example
   * ```typescript
   * const checkoutPayer = PayerAdapter.toCheckoutFormat(crmPayer);
   * await checkoutService.complete({ payer: checkoutPayer, ... });
   * ```
   */
  static toCheckoutFormat(crmPayer: CrmPayer | undefined): Payer | undefined {
    if (!crmPayer) {
      return undefined;
    }

    return {
      reference: { id: crmPayer.id },
      source: crmPayer.id,
      payerType: crmPayer.payerType,
      payerNumber: crmPayer.payerNumber,
      payerStatus: crmPayer.payerStatus,
      gender: crmPayer.gender,
      title: crmPayer.title,
      firstName: crmPayer.firstName,
      lastName: crmPayer.lastName,
      communicationDetails: crmPayer.communicationDetails
        ? { ...crmPayer.communicationDetails }
        : undefined,
      organisation: crmPayer.organisation
        ? { ...crmPayer.organisation }
        : undefined,
      address: crmPayer.address ? { ...crmPayer.address } : undefined,
    };
  }

  /**
   * Type guard for CRM payer response
   *
   * @param value - Value to check
   * @returns true if value is a valid CRM payer with required fields
   */
  static isValidCrmPayer(value: unknown): value is CrmPayer {
    if (typeof value !== 'object' || value === null) return false;

    const payer = value as CrmPayer;
    return (
      typeof payer.id === 'number' &&
      (payer.payerNumber === undefined || typeof payer.payerNumber === 'string')
    );
  }
}
