<?php

namespace Drupal\commerce_payment\EventSubscriber;

use Drupal\commerce_order\AddressBookInterface;
use Drupal\commerce_order\Event\OrderAssignEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class OrderAssignSubscriber implements EventSubscriberInterface {

  /**
   * Constructs a new AddressBookSubscriber object.
   *
   * @param \Drupal\commerce_order\AddressBookInterface $addressBook
   *   The address book.
   */
  public function __construct(protected AddressBookInterface $addressBook) {}

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    $events = [
      'commerce_order.order.assign' => 'onAssign',
    ];
    return $events;
  }

  /**
   * Assigns anonymous payment methods to the new customer.
   *
   * @param \Drupal\commerce_order\Event\OrderAssignEvent $event
   *   The event.
   */
  public function onAssign(OrderAssignEvent $event) {
    $order = $event->getOrder();
    if ($order->get('payment_method')->isEmpty()) {
      return;
    }

    $customer = $event->getCustomer();
    /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $payment_method */
    $payment_method = $order->get('payment_method')->entity;
    if ($payment_method && empty($payment_method->getOwnerId())) {
      $payment_method_profile = $payment_method->getBillingProfile();
      if ($payment_method_profile && $this->addressBook->needsCopy($payment_method_profile)) {
        $this->addressBook->copy($payment_method_profile, $customer);
        // The data field is not copied by default but needs to be.
        // For example, both profiles need to have an address_book_profile_id.
        $billing_profile = $order->getBillingProfile();
        if ($payment_method_profile->equalToProfile($billing_profile)) {
          $billing_profile->populateFromProfile($payment_method_profile, ['data']);
          $billing_profile->save();
        }
      }
      $payment_method->setOwner($customer);
      $payment_method->save();
    }
  }

}
