<?php

/**
 * Base Subscription Email Class
 *
 * Abstract base class for all subscription-related emails.
 * Extends WC_Email for WooCommerce integration.
 *
 * @package ArraySubs\Features\Emails\Abstracts
 * @since 1.0.0
 */

namespace ArraySubs\Features\Emails\Abstracts;

use ArraySubs\Supports\Config;

defined('ABSPATH') || exit;

/**
 * Base class for subscription emails
 */
abstract class BaseSubscriptionEmail extends \WC_Email
{
    /**
     * Subscription ID
     *
     * @var int
     */
    protected int $subscription_id = 0;

    /**
     * Subscription post object
     *
     * @var \WP_Post|null
     */
    protected ?\WP_Post $subscription = null;

    /**
     * Related order (for renewal/payment emails)
     *
     * @var \WC_Order|null
     */
    protected ?\WC_Order $order = null;

    /**
     * Constructor
     */
    public function __construct()
    {
        // Set template paths - use Config::get() for plugin paths
        $this->template_base = Config::get('plugin.src_path') . '/Features/Emails/templates/';

        // Default placeholders with sample values for preview.
        $default_placeholders = [
            '{site_title}'          => $this->get_blogname(),
            '{site_address}'        => wp_parse_url(home_url(), PHP_URL_HOST),
            '{store_address}'       => $this->get_formatted_store_address(),
            '{site_url}'            => home_url(),
            '{store_email}'         => get_option('admin_email'),
            '{subscription_id}'     => '12345',
            '{customer_name}'       => __('John Doe', 'arraysubs'),
            '{customer_first_name}' => __('John', 'arraysubs'),
            '{customer_email}'      => 'customer@example.com',
            '{product_name}'        => __('Sample Subscription Product', 'arraysubs'),
            '{next_payment_date}'   => \arraysubs_format_timestamp_local(
                strtotime('+30 days', time()),
                \get_option('date_format')
            ),
            '{start_date}'          => \arraysubs_format_timestamp_local(
                \current_time('timestamp', true),
                \get_option('date_format')
            ),
            '{recurring_amount}'    => wc_price(29.99),
            '{billing_period}'      => __('every month', 'arraysubs'),
            '{payment_method}'      => __('Direct bank transfer', 'arraysubs'),
            '{subscription_status}' => __('Active', 'arraysubs'),
            '{my_account_url}'      => wc_get_account_endpoint_url('subscriptions'),
        ];

        $this->placeholders = array_merge($default_placeholders, $this->placeholders);

        parent::__construct();
    }

    /**
     * Get the WooCommerce store address for email placeholder previews.
     *
     * @return string
     */
    protected function get_formatted_store_address(): string
    {
        if (!function_exists('WC') || !WC() || empty(WC()->countries)) {
            return (string) wp_parse_url(home_url(), PHP_URL_HOST);
        }

        $address = WC()->countries->get_formatted_address([
            'address_1' => WC()->countries->get_base_address(),
            'address_2' => WC()->countries->get_base_address_2(),
            'city'      => WC()->countries->get_base_city(),
            'state'     => WC()->countries->get_base_state(),
            'country'   => WC()->countries->get_base_country(),
            'postcode'  => WC()->countries->get_base_postcode(),
        ]);

        $address = wp_specialchars_decode($address);
        $address = preg_replace('/<br\/?>/i', ', ', $address);

        return !empty($address) ? $address : (string) wp_parse_url(home_url(), PHP_URL_HOST);
    }

    /**
     * Trigger the email
     *
     * @param int   $subscription_id Subscription ID
     * @param array $args            Additional arguments
     */
    public function trigger(int $subscription_id, array $args = []): void
    {
        $this->subscription_id = $subscription_id;
        $this->subscription = arraysubs_get_subscription($subscription_id);

        if (!$this->subscription instanceof \WP_Post) {
            return;
        }

        // Set order if provided
        if (!empty($args['order_id'])) {
            $order = wc_get_order($args['order_id']);
            $this->order = $order instanceof \WC_Order ? $order : null;
        }

        $this->setup_locale();
        $this->recipient = $this->get_customer_email();
        $this->populate_placeholders($args);

        if ($this->is_enabled() && $this->get_recipient()) {
            $result = $this->send(
                $this->get_recipient(),
                $this->get_subject(),
                $this->get_content(),
                $this->get_headers(),
                $this->get_attachments()
            );
            // Add subscription note
            if ($result && function_exists('arraysubs_add_subscription_note')) {
                arraysubs_add_subscription_note(
                    $subscription_id,
                    sprintf(
                        /* translators: %s: email type */
                        __('Email sent: %s', 'arraysubs'),
                        $this->get_title()
                    ),
                    'system',
                    0,
                    [],
                    'email'
                );
            }
        }

        $this->restore_locale();
    }

    /**
     * Get customer email address
     *
     * @return string
     */
    protected function get_customer_email(): string
    {
        $customer_id = get_post_meta($this->subscription_id, '_customer_id', true);
        $customer_email = get_post_meta($this->subscription_id, '_customer_email', true);

        // Try from meta first
        if (!empty($customer_email)) {
            return sanitize_email($customer_email);
        }

        // Try from user
        if (!empty($customer_id)) {
            $user = get_user_by('ID', $customer_id);
            if ($user) {
                return $user->user_email;
            }
        }

        return '';
    }

    /**
     * Get the default admin notification email.
     *
     * @return string
     */
    protected function get_default_admin_email(): string
    {
        return function_exists('arraysubs_get_admin_email')
            ? arraysubs_get_admin_email()
            : get_option('admin_email');
    }

    /**
     * Get admin email recipient list, preserving WC per-email overrides.
     *
     * @return string
     */
    protected function get_admin_email_recipient(): string
    {
        return $this->get_option('recipient', $this->get_default_admin_email());
    }

    /**
     * Get customer data
     *
     * @return array
     */
    protected function get_customer_data(): array
    {
        if (!$this->subscription_id) {
            return [
                'id'         => 0,
                'email'      => $this->placeholders['{customer_email}'] ?? 'customer@example.com',
                'first_name' => $this->placeholders['{customer_first_name}'] ?? __('John', 'arraysubs'),
                'last_name'  => __('Doe', 'arraysubs'),
                'full_name'  => $this->placeholders['{customer_name}'] ?? __('John Doe', 'arraysubs'),
            ];
        }

        $customer_id = get_post_meta($this->subscription_id, '_customer_id', true);
        $customer_email = get_post_meta($this->subscription_id, '_customer_email', true);

        $data = [
            'id'         => $customer_id,
            'email'      => $customer_email,
            'first_name' => '',
            'last_name'  => '',
            'full_name'  => '',
        ];

        if (!empty($customer_id)) {
            $user = get_user_by('ID', $customer_id);
            if ($user) {
                $data['email']      = $data['email'] ?: $user->user_email;
                $data['first_name'] = $user->first_name ?: $user->display_name;
                $data['last_name']  = $user->last_name;
                $data['full_name']  = trim($user->first_name . ' ' . $user->last_name);
                if (empty($data['full_name'])) {
                    $data['full_name'] = $user->display_name;
                }
            }
        }

        // Fallback to billing info from related order
        if ($this->order && empty($data['first_name'])) {
            $data['first_name'] = $this->order->get_billing_first_name();
            $data['last_name']  = $this->order->get_billing_last_name();
            $data['full_name']  = $this->order->get_formatted_billing_full_name();
        }

        return $data;
    }

    /**
     * Populate email placeholders
     *
     * @param array $args Additional arguments
     */
    protected function populate_placeholders(array $args = []): void
    {
        $customer = $this->get_customer_data();

        // Build billing period string
        $interval = get_post_meta($this->subscription_id, '_billing_interval', true);
        $period = get_post_meta($this->subscription_id, '_billing_period', true);
        $billing_period = \arraysubs_format_billing_period($interval, $period);

        // Get product name with variation suffix
        $product_name = \arraysubs_get_subscription_product_name_by_subscription($this->subscription_id);

        $this->placeholders['{subscription_id}']    = $this->subscription_id;
        $this->placeholders['{customer_name}']      = $customer['full_name'];
        $this->placeholders['{customer_first_name}'] = $customer['first_name'];
        $this->placeholders['{customer_email}']     = $customer['email'];
        $this->placeholders['{product_name}']       = $product_name;
        $this->placeholders['{start_date}']         = \arraysubs_format_date_local(
            get_post_meta($this->subscription_id, '_start_date', true)
        );
        $this->placeholders['{next_payment_date}']  = \arraysubs_format_date_local(
            get_post_meta($this->subscription_id, '_next_payment_date', true)
        );
        $this->placeholders['{recurring_amount}']   = wc_price(
            get_post_meta($this->subscription_id, '_recurring_amount', true)
        );
        $this->placeholders['{billing_period}']     = $billing_period;
        $this->placeholders['{payment_method}']     = get_post_meta($this->subscription_id, '_payment_method_title', true) ?: __('N/A', 'arraysubs');
        $this->placeholders['{subscription_status}'] = \arraysubs_get_status_label(
            $this->subscription->post_status
        );
        $this->placeholders['{my_account_url}']     = wc_get_account_endpoint_url('subscriptions');
    }

    /**
     * Get email content HTML
     *
     * @return string
     */
    public function get_content_html(): string
    {
        return wc_get_template_html(
            $this->template_html,
            $this->get_template_args(false),
            '',
            $this->template_base
        );
    }

    /**
     * Get email content plain text
     *
     * @return string
     */
    public function get_content_plain(): string
    {
        return wc_get_template_html(
            $this->template_plain,
            $this->get_template_args(true),
            '',
            $this->template_base
        );
    }

    /**
     * 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
    {
        // Get product from subscription meta
        $product_id = $this->subscription_id
            ? get_post_meta($this->subscription_id, '_product_id', true)
            : 0;
        $product = $product_id ? wc_get_product($product_id) : null;
        $product_name = $product ? $product->get_name() : (string) $this->placeholders['{product_name}'];

        // Get subscription status safely
        $subscription_status = $this->subscription
            ? arraysubs_get_status_label($this->subscription->post_status)
            : (string) $this->placeholders['{subscription_status}'];

        $start_date = $this->subscription_id ? get_post_meta($this->subscription_id, '_start_date', true) : '';
        $next_payment_date = $this->subscription_id ? get_post_meta($this->subscription_id, '_next_payment_date', true) : '';
        $recurring_amount = $this->subscription_id ? get_post_meta($this->subscription_id, '_recurring_amount', true) : '';
        $interval = $this->subscription_id ? get_post_meta($this->subscription_id, '_billing_interval', true) : '';
        $period = $this->subscription_id ? get_post_meta($this->subscription_id, '_billing_period', true) : '';

        return [
            'arraysubs_subscription'        => $this->subscription,
            'arraysubs_subscription_id'     => $this->subscription_id,
            'arraysubs_subscription_number' => $this->subscription_id ?: $this->placeholders['{subscription_id}'],
            'arraysubs_subscription_status' => $subscription_status,
            'arraysubs_product'             => $product,
            'arraysubs_product_name'        => $product_name,
            'arraysubs_order'               => $this->order,
            'arraysubs_customer'            => $this->get_customer_data(),
            'arraysubs_recurring_amount'    => $recurring_amount !== '' ? wc_price($recurring_amount) : $this->placeholders['{recurring_amount}'],
            'arraysubs_billing_period'      => ($interval !== '' && $period !== '') ? \arraysubs_format_billing_period($interval, $period) : $this->placeholders['{billing_period}'],
            'arraysubs_start_date'          => !empty($start_date) ? \arraysubs_format_date_local($start_date) : $this->placeholders['{start_date}'],
            'arraysubs_next_payment_date'   => !empty($next_payment_date) ? \arraysubs_format_date_local($next_payment_date) : $this->placeholders['{next_payment_date}'],
            'arraysubs_payment_method_title' => $this->subscription_id
                ? (get_post_meta($this->subscription_id, '_payment_method_title', true) ?: __('N/A', 'arraysubs'))
                : $this->placeholders['{payment_method}'],
            'arraysubs_my_account_url'      => $this->placeholders['{my_account_url}'],
            'arraysubs_email_heading'       => $this->get_heading(),
            'arraysubs_additional_content'  => $this->get_additional_content(),
            'arraysubs_sent_to_admin'       => false,
            'arraysubs_plain_text'          => $plain_text,
            'arraysubs_email'               => $this,
        ];
    }

    /**
     * Get default additional content
     *
     * @return string
     */
    public function get_default_additional_content(): string
    {
        return '';
    }

    /**
     * Initialize form fields for WooCommerce email settings
     */
    public function init_form_fields(): void
    {
        $placeholder_text = sprintf(
            /* translators: %s: comma-separated list of email template placeholders with code tags */
            __('Available placeholders: %s', 'arraysubs'),
            '<code>' . implode('</code>, <code>', array_keys($this->placeholders)) . '</code>'
        );

        $this->form_fields = [
            'enabled' => [
                'title'   => __('Enable/Disable', 'arraysubs'),
                'type'    => 'checkbox',
                'label'   => __('Enable this email notification', 'arraysubs'),
                'default' => 'yes',
            ],
            'subject' => [
                'title'       => __('Subject', 'arraysubs'),
                'type'        => 'text',
                'desc_tip'    => true,
                'description' => $placeholder_text,
                'placeholder' => $this->get_default_subject(),
                'default'     => '',
            ],
            'heading' => [
                'title'       => __('Email heading', 'arraysubs'),
                'type'        => 'text',
                'desc_tip'    => true,
                'description' => $placeholder_text,
                'placeholder' => $this->get_default_heading(),
                'default'     => '',
            ],
            'additional_content' => [
                'title'       => __('Additional content', 'arraysubs'),
                'description' => __('Text to appear below the main email content.', 'arraysubs') . ' ' . $placeholder_text,
                'css'         => 'width:400px; height: 75px;',
                'placeholder' => __('N/A', 'arraysubs'),
                'type'        => 'textarea',
                'default'     => $this->get_default_additional_content(),
                'desc_tip'    => true,
            ],
            'email_type' => [
                'title'       => __('Email type', 'arraysubs'),
                'type'        => 'select',
                'description' => __('Choose which format of email to send.', 'arraysubs'),
                'default'     => 'html',
                'class'       => 'email_type wc-enhanced-select',
                'options'     => $this->get_email_type_options(),
                'desc_tip'    => true,
            ],
        ];
    }

    /**
     * Get default subject
     *
     * @return string
     */
    public function get_default_subject(): string
    {
        return $this->subject;
    }

    /**
     * Get default heading
     *
     * @return string
     */
    public function get_default_heading(): string
    {
        return $this->heading;
    }
}
