<?php

/**
 * Renewal Reminder Email
 *
 * Sent to customers X days before their next payment is due.
 *
 * @package ArraySubs\Features\Emails\Emails
 * @since 1.0.0
 */

namespace ArraySubs\Features\Emails\Emails;

defined('ABSPATH') || exit;

use ArraySubs\Features\Emails\Abstracts\BaseSubscriptionEmail;

/**
 * Renewal Reminder Email class
 */
class RenewalReminderEmail extends BaseSubscriptionEmail
{
    /**
     * Days before renewal
     *
     * @var int
     */
    protected int $days_before = 3;

    /**
     * Reminder context.
     *
     * @var string
     */
    protected string $reminder_context = 'renewal';

    /**
     * Context-specific date.
     *
     * @var string
     */
    protected string $context_date = '';

    /**
     * Context-specific date label.
     *
     * @var string
     */
    protected string $context_date_label = '';

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->id             = 'arraysubs_renewal_reminder';
        $this->customer_email = true;
        $this->title          = __('[ArraySubs] Renewal Reminder', 'arraysubs');
        $this->description    = __('Renewal reminder emails are sent to customers before their subscription payment is due.', 'arraysubs');

        $this->heading        = __('Your subscription renews soon', 'arraysubs');
        $this->subject        = __('[{site_title}] Your subscription #{subscription_id} renews soon', 'arraysubs');

        $this->template_html  = 'customer-renewal-reminder.php';
        $this->template_plain = 'plain/customer-renewal-reminder.php';

        // Add days_before placeholder with sample value for preview
        $this->placeholders['{days_before}'] = '3';
        $this->placeholders['{trial_end_date}'] = \arraysubs_format_timestamp_local(
            strtotime('+3 days', time()),
            \get_option('date_format')
        );
        $this->placeholders['{subscription_end_date}'] = \arraysubs_format_timestamp_local(
            strtotime('+3 days', time()),
            \get_option('date_format')
        );

        parent::__construct();
    }

    /**
     * Populate placeholders
     *
     * @param array $args Additional arguments
     */
    protected function populate_placeholders(array $args = []): void
    {
        parent::populate_placeholders($args);

        $this->days_before = absint($args['days_before'] ?? 3) ?: 3;
        $this->reminder_context = $this->detectReminderContext();
        $this->applyContextCopy();

        $this->placeholders['{days_before}'] = $this->days_before;
        $this->placeholders['{trial_end_date}'] = $this->getTrialEndDateDisplay();
        $this->placeholders['{subscription_end_date}'] = $this->getSubscriptionEndDateDisplay();
    }

    /**
     * Get template arguments
     *
     * @param bool $plain_text Whether this is plain text email
     * @return array
     */
    protected function get_template_args(bool $plain_text = false): array
    {
        $args = parent::get_template_args($plain_text);
        $args['arraysubs_days_before'] = $this->days_before;
        $args['arraysubs_reminder_context'] = $this->reminder_context;
        $args['arraysubs_context_date'] = $this->context_date;
        $args['arraysubs_context_date_label'] = $this->context_date_label;
        return $args;
    }

    /**
     * Detect which reminder copy should be used.
     *
     * @return string
     */
    private function detectReminderContext(): string
    {
        if ($this->subscription instanceof \WP_Post && 'arraysubs-trial' === $this->subscription->post_status) {
            return 'trial';
        }

        $end_date = (string) get_post_meta($this->subscription_id, '_end_date', true);
        if ($this->isValidStoredDate($end_date)) {
            return 'expiring';
        }

        return 'renewal';
    }

    /**
     * Apply context-specific subject, heading, and date metadata.
     *
     * @return void
     */
    private function applyContextCopy(): void
    {
        if ('trial' === $this->reminder_context) {
            $this->heading = __('Your trial ends soon', 'arraysubs');
            $this->subject = __('[{site_title}] Your trial for {product_name} ends soon', 'arraysubs');
            $this->context_date = $this->getTrialEndDateDisplay();
            $this->context_date_label = __('Trial End Date', 'arraysubs');
            return;
        }

        if ('expiring' === $this->reminder_context) {
            $this->heading = __('Your subscription is ending soon', 'arraysubs');
            $this->subject = __('[{site_title}] Your subscription #{subscription_id} is ending soon', 'arraysubs');
            $this->context_date = $this->getSubscriptionEndDateDisplay();
            $this->context_date_label = __('End Date', 'arraysubs');
            return;
        }

        $this->heading = __('Your subscription renews soon', 'arraysubs');
        $this->subject = __('[{site_title}] Your subscription #{subscription_id} renews soon', 'arraysubs');
        $this->context_date = $this->getNextPaymentDateDisplay();
        $this->context_date_label = __('Next Payment Date', 'arraysubs');
    }

    /**
     * Get the trial end date display string.
     *
     * @return string
     */
    private function getTrialEndDateDisplay(): string
    {
        $trial_end_date = (string) get_post_meta($this->subscription_id, '_trial_end_date', true);
        if (!$this->isValidStoredDate($trial_end_date)) {
            $trial_end_date = (string) get_post_meta($this->subscription_id, '_next_payment_date', true);
        }

        return $this->isValidStoredDate($trial_end_date) ? \arraysubs_format_date_local($trial_end_date) : __('N/A', 'arraysubs');
    }

    /**
     * Get the subscription end date display string.
     *
     * @return string
     */
    private function getSubscriptionEndDateDisplay(): string
    {
        $end_date = (string) get_post_meta($this->subscription_id, '_end_date', true);

        return $this->isValidStoredDate($end_date) ? \arraysubs_format_date_local($end_date) : __('N/A', 'arraysubs');
    }

    /**
     * Get the next payment date display string.
     *
     * @return string
     */
    private function getNextPaymentDateDisplay(): string
    {
        $next_payment_date = (string) get_post_meta($this->subscription_id, '_next_payment_date', true);

        return $this->isValidStoredDate($next_payment_date) ? \arraysubs_format_date_local($next_payment_date) : __('N/A', 'arraysubs');
    }

    /**
     * Check whether a stored MySQL date is usable.
     *
     * @param string $date Date value.
     * @return bool
     */
    private function isValidStoredDate(string $date): bool
    {
        return '' !== $date && '0000-00-00 00:00:00' !== $date && false !== strtotime($date);
    }

    /**
     * Get default additional content
     *
     * @return string
     */
    public function get_default_additional_content(): string
    {
        return __('If you wish to make any changes to your subscription, please visit your account page.', 'arraysubs');
    }

    /**
     * Initialize form fields
     */
    public function init_form_fields(): void
    {
        parent::init_form_fields();

        // Add days before field
        $this->form_fields['days_before'] = [
            'title'       => __('Days before renewal', 'arraysubs'),
            'type'        => 'number',
            'description' => __('Number of days before the renewal date to send this email.', 'arraysubs'),
            'default'     => '3',
            'desc_tip'    => true,
            'custom_attributes' => [
                'min' => '1',
                'max' => '30',
            ],
        ];
    }
}
