<?php
/**
 * TranslatableEmailSubjectsUpgrade.php.
 *
 * @package RewardsWP
 */

namespace Awesomemotive\Rewardswp\Database\Upgrades;

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

use Awesomemotive\Rewardswp\Abstracts\AbstractDatabaseUpgrade;
use Awesomemotive\Rewardswp\Factories\MailerFactory;
use Awesomemotive\Rewardswp\Services\EmailsService;

/**
 * Clears un-customised email subjects so they resolve from the translatable default.
 *
 * Earlier versions seeded the resolved (English) default subject into the emails table,
 * which then shadowed the translatable default at send time. Clearing the un-customised
 * ones lets get_subject() fall through to get_default_subject() per request/locale.
 *
 * @since 1.4.4
 */
class TranslatableEmailSubjectsUpgrade extends AbstractDatabaseUpgrade {

	/**
	 * The version this upgrade targets.
	 *
	 * @since 1.4.4
	 * @var string
	 */
	protected string $version = '1.4.4';

	/**
	 * Emails service instance.
	 *
	 * @since 1.4.4
	 * @var EmailsService
	 */
	private EmailsService $emails_service;

	/**
	 * Mailer factory instance.
	 *
	 * @since 1.4.4
	 * @var MailerFactory
	 */
	private MailerFactory $mailer_factory;

	/**
	 * Constructor.
	 *
	 * @since 1.4.4
	 *
	 * @param EmailsService $emails_service The emails service instance.
	 * @param MailerFactory $mailer_factory The mailer factory instance.
	 */
	public function __construct( EmailsService $emails_service, MailerFactory $mailer_factory ) {
		$this->emails_service = $emails_service;
		$this->mailer_factory = $mailer_factory;
	}

	/**
	 * Run the upgrade.
	 *
	 * @since 1.4.4
	 * @return void
	 */
	public function up(): void {
		$emails = $this->emails_service->get_emails( [], 100, 1 );

		if ( empty( $emails ) ) {
			return;
		}

		/*
		 * Resolve each default against the source (English) strings so the comparison is
		 * locale-independent. Switching to en_US unloads the active translations, so __()
		 * returns the original source string that was seeded.
		 */
		$switched         = function_exists( 'switch_to_locale' ) ? switch_to_locale( 'en_US' ) : false;
		$english_defaults = [];

		foreach ( $emails as $email ) {
			$mailer = $this->mailer_factory->get_mailer( $email->name );

			if ( $mailer ) {
				$english_defaults[ $email->name ] = $mailer->get_default_subject_for_seeding();
			}
		}

		if ( $switched ) {
			restore_previous_locale();
		}

		/*
		 * A subject seeded from a default that has SINCE been changed in code won't match
		 * the current default resolved above, so without this it would be treated as
		 * customised and never cleared (leaving it stuck on a stale English string).
		 * Recognise the known previous (source-string) defaults too.
		 */
		$legacy_defaults = $this->get_legacy_default_subjects();

		foreach ( $emails as $email ) {
			if ( '' === $email->subject ) {
				continue;
			}

			$is_current_default = isset( $english_defaults[ $email->name ] )
				&& $email->subject === $english_defaults[ $email->name ];

			$is_legacy_default = isset( $legacy_defaults[ $email->name ] )
				&& in_array( $email->subject, $legacy_defaults[ $email->name ], true );

			// Only clear subjects still equal to a (current or previous) default; customised subjects differ and are kept.
			if ( $is_current_default || $is_legacy_default ) {
				$this->emails_service->update_email( $email->id, [ 'subject' => '' ] );
			}
		}
	}

	/**
	 * Previous default subjects (source strings) that earlier versions seeded into the
	 * emails table before the defaults were changed in code. Keyed by email name.
	 *
	 * @since 1.4.4
	 *
	 * @return array<string, string[]>
	 */
	private function get_legacy_default_subjects(): array {
		return [
			'points_earned'     => [ 'You earned points! {points_earned_formatted} added to your account' ],
			'reward_redemption' => [ 'Reward Redeemed! Your {reward_title} is ready' ],
			'birthday_reward'   => [ 'Happy Birthday, {member_name}! {points_earned_formatted} birthday bonus added' ],
		];
	}
}
