<?php
/**
 * @package Hafenstudios\Kurato
 */

namespace Hafenstudios\Kurato\Intake;

use Hafenstudios\Core\Events\EventBus;
use Hafenstudios\Kurato\Db\ContactRepository;
use Hafenstudios\Kurato\Db\ListRepository;
use Hafenstudios\Kurato\Db\SubscriptionRepository;

defined( 'ABSPATH' ) || exit;

/**
 * Verzahnt Newsletter-Anmeldungen aus Leadlotse mit der Kurato-Abo-Verwaltung
 * (K4-Konzept Abschnitt 3).
 *
 * - `contact_intake` (nach dem LeadIntake, mit Kontakt-ID): bei Zweck Newsletter
 *   wird ein Abo in der Default-Liste angelegt. Mit Formular-DOI als `pending`
 *   (die DOI-Mail verschickt weiterhin Leadlotse), ohne DOI direkt `confirmed`.
 * - `lead_confirmed` (nach dem Klick auf den Bestaetigungslink): alle offenen
 *   Abos des Kontakts werden bestaetigt. Der Uebergang ist idempotent
 *   (Defense in depth zusaetzlich zum Leadlotse-Fix des doppelten Events).
 */
final class SubscriptionIntake {

	private ContactRepository $contacts;

	private ListRepository $lists;

	private SubscriptionRepository $subscriptions;

	/**
	 * @param ContactRepository      $contacts      Kontakt-Repository.
	 * @param ListRepository         $lists         Listen-Repository.
	 * @param SubscriptionRepository $subscriptions Abo-Repository.
	 */
	public function __construct( ContactRepository $contacts, ListRepository $lists, SubscriptionRepository $subscriptions ) {
		$this->contacts      = $contacts;
		$this->lists         = $lists;
		$this->subscriptions = $subscriptions;
	}

	/**
	 * Registriert die Event-Listener.
	 *
	 * @return void
	 */
	public function register(): void {
		EventBus::on( 'contact_intake', array( $this, 'on_contact_intake' ), 20, 3 );
		EventBus::on( 'lead_confirmed', array( $this, 'on_lead_confirmed' ), 10, 1 );
	}

	/**
	 * Legt bei einer Newsletter-Anmeldung ein Abo an.
	 *
	 * @param int                  $contact_id Kontakt-ID (aus dem LeadIntake).
	 * @param array<string, mixed> $lead       Ursprungs-Payload von lead_created.
	 * @param bool                 $created    Ob der Kontakt neu angelegt wurde (ungenutzt).
	 * @return void
	 */
	public function on_contact_intake( $contact_id, $lead, $created ): void {
		$contact_id = (int) $contact_id;
		if ( $contact_id <= 0 || ! is_array( $lead ) ) {
			return;
		}
		// Nur Newsletter-Anmeldungen erzeugen ein Abo. Kontakt-/Anfrageformulare
		// landen als Kontakt in der Pipeline, aber nicht in einer Verteilerliste.
		if ( 'newsletter' !== (string) ( $lead['purpose'] ?? '' ) ) {
			return;
		}

		$list_id = $this->lists->ensure_default();
		if ( $list_id <= 0 ) {
			return;
		}

		// Mit Formular-DOI: pending (Leadlotse verschickt die Bestaetigungsmail).
		// Ohne DOI: der Betreiber hat es bewusst abgeschaltet, direkt confirmed.
		$status     = ! empty( $lead['doi'] ) ? 'pending' : 'confirmed';
		$consent_id = absint( $lead['consent_id'] ?? 0 );

		$this->subscriptions->subscribe( $list_id, $contact_id, $status, 'leadlotse', $consent_id );
	}

	/**
	 * Bestaetigt die offenen Abos eines Kontakts nach dem DOI-Klick.
	 *
	 * @param array<string, mixed> $payload lead_confirmed-Payload.
	 * @return void
	 */
	public function on_lead_confirmed( $payload ): void {
		if ( ! is_array( $payload ) ) {
			return;
		}
		$email = sanitize_email( (string) ( $payload['email'] ?? '' ) );
		if ( '' === $email ) {
			return;
		}
		$contact = $this->contacts->find_by_email( $email );
		if ( null === $contact ) {
			return;
		}
		$this->subscriptions->confirm_pending_for_contact( (int) $contact['id'] );
	}
}
