<?php
/**
 * Cart Recovery — Composition Result DTO
 *
 * Immutable output of the AI composer. `html` / `text` may contain the
 * literal `{{COUPON_CODE}}` placeholder when the context carried
 * `has_coupon = true` — the Phase 5 mailer is responsible for
 * interpolating the real per-recipient coupon code at send time so the
 * cache can safely be shared across recipients with identical
 * (cart, transcript, locale, stage) fingerprints.
 *
 * @package Niwa_AI
 * @since   0.12.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class Niwa_AI_Cart_Recovery_Composition_Result {

	public function __construct(
		public readonly string $subject,
		public readonly string $preview_text,
		public readonly string $html,
		public readonly string $text,
		public readonly bool $from_cache = false,
		public readonly string $model_used = '',
		public readonly bool $is_fallback = false
	) {}

	/**
	 * @return array<string, mixed>
	 */
	public function to_array(): array {
		return array(
			'subject'      => $this->subject,
			'preview_text' => $this->preview_text,
			'html'         => $this->html,
			'text'         => $this->text,
			'from_cache'   => $this->from_cache,
			'model_used'   => $this->model_used,
			'is_fallback'  => $this->is_fallback,
		);
	}

	public static function from_array( array $data ): self {
		return new self(
			(string) ( $data['subject'] ?? '' ),
			(string) ( $data['preview_text'] ?? '' ),
			(string) ( $data['html'] ?? '' ),
			(string) ( $data['text'] ?? '' ),
			(bool) ( $data['from_cache'] ?? false ),
			(string) ( $data['model_used'] ?? '' ),
			(bool) ( $data['is_fallback'] ?? false )
		);
	}
}
