<?php
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Service for handling SMTP configuration, HTML email rendering, and core mail dispatch.
 */
class NEXDIRECTORY_Email_Service {

    /**
     * @var NEXDIRECTORY_Date_Helper
     */
    private $date_helper;

    /**
     * @var mixed Logger service (e.g., NEXDIRECTORY_Runtime_Log_Service)
     */
    private $logger;

    /**
     * Constructor.
     * * @param NEXDIRECTORY_Date_Helper $date_helper Required to format dates in email tokens.
     * @param mixed           $logger      Required to log SMTP configuration failures.
     */
    public function __construct($date_helper, $logger) {
        $this->date_helper = $date_helper;
        $this->logger = $logger;
    }

    /**
     * Returns the default text/HTML templates for system emails.
     */
    public function get_default_event_email_templates() {
        return [
            'nexdirectory_email_subject_confirmation' => __('Listing submission received: {event_title}', 'nexdirectory'),
            'nexdirectory_email_subject_reminder' => __('Reminder: {event_title}', 'nexdirectory'),
            'nexdirectory_email_subject_ticket_confirmation' => __('Ticket confirmation: {event_title}', 'nexdirectory'),
            'nexdirectory_email_subject_update' => __('Listing update: {event_title}', 'nexdirectory'),
            'nexdirectory_email_subject_cancellation' => __('Listing status changed: {event_title}', 'nexdirectory'),
            'nexdirectory_email_subject_extension_potential_owner' => __('Your listing was added to {site_name}: {listing_title}', 'nexdirectory'),
            'nexdirectory_email_body_confirmation' => __(
                "Hi,\n\nYour listing \"{event_title}\" has been received and is now pending review.\nDate: {event_date}\nLink: {event_url}\n\nWe will notify you when moderation is complete.",
                'nexdirectory'
            ),
            'nexdirectory_email_body_reminder' => __(
                "Reminder:\n\"{event_title}\" starts soon. This notification is scheduled {reminder_timing}.\nDate: {event_date}\nLink: {event_url}",
                'nexdirectory'
            ),
            'nexdirectory_email_body_ticket_confirmation' => __(
                "Hi {attendee_name},\n\nYour ticket status for \"{event_title}\" is {ticket_status}.\nTicket ID: {ticket_id}\nAmount: {ticket_total}\nPayment method: {ticket_payment_method}\nGateway: {ticket_gateway}\nPurchased: {ticket_purchase_date}\nDate: {event_date}\nLink: {event_url}\nVerify ticket: {ticket_verification_url}\nQR image: {ticket_qr_image_url}\n\nThank you.",
                'nexdirectory'
            ),
            'nexdirectory_email_body_update' => __(
                "Update:\nYour listing \"{event_title}\" status is now {status}.\nDate: {event_date}\nLink: {event_url}\n\n{moderator_note}",
                'nexdirectory'
            ),
            'nexdirectory_email_body_cancellation' => __(
                "Important update:\nYour listing \"{event_title}\" status is now {status}.\nDate: {event_date}\nLink: {event_url}\n\nModerator note:\n{moderator_note}",
                'nexdirectory'
            ),
            'nexdirectory_email_body_extension_potential_owner' => __(
                "Hello,\n\nA listing matching your event has been added to {site_name}.\n\nTitle: {listing_title}\nView listing: {listing_url}\nClaim this listing: {claim_url}\nSource page: {source_url}\n\nIf this is your listing, you can claim ownership. If you prefer removal, please contact the site administrator.",
                'nexdirectory'
            ),
        ];
    }

    /**
     * Gets a specific default email template value, falling back to a provided string.
     */
    public function get_default_event_email_template_value($key, $fallback = '') {
        $defaults = $this->get_default_event_email_templates();
        if (isset($defaults[$key])) {
            return (string) $defaults[$key];
        }
        return (string) $fallback;
    }

    /**
     * Locates a physical email template file, allowing theme overrides.
     */
    public function locate_email_template($template_name) {
        $template_name = ltrim((string) $template_name, '/');
        if ($template_name === '') {
            return '';
        }

        // 1. Check if the active theme has overridden the template
        $theme_path = locate_template('nexdirectory/emails/' . $template_name);
        if (is_string($theme_path) && $theme_path !== '' && is_readable($theme_path)) {
            return $theme_path;
        }

        // 2. Fall back to the core plugin template
        $plugin_path = plugin_dir_path(NEXDIRECTORY_PLUGIN_FILE) . 'templates/emails/' . $template_name;
        if (is_readable($plugin_path)) {
            return $plugin_path;
        }

        return '';
    }

    /**
     * Renders a PHP email template file into an HTML string.
     */
    public function render_email_template($template_name, array $context = []) {
        $path = $this->locate_email_template($template_name);
        if ($path === '') {
            return '';
        }
        
        extract($context, EXTR_SKIP);
        ob_start();
        include $path;
        return (string) ob_get_clean();
    }

    /**
     * Builds the same branded HTML document used for a live platform email.
     *
     * Keeping rendering separate from delivery lets administrators preview a
     * notification without sending it or duplicating the email design.
     *
     * @param string $subject       Email subject.
     * @param string $template_name Template filename, relative to the email directory.
     * @param array  $context       Template and shell context.
     * @return string Rendered HTML, or an empty string when there is no content.
     */
    public function render_platform_email($subject, $template_name, array $context = []) {
        $subject = sanitize_text_field((string) $subject);
        if ($subject === '') {
            return '';
        }

        $custom_body_html = (string) ($context['custom_body_html'] ?? '');
        $body_html = '';

        if ($custom_body_html !== '') {
            $body_html = wp_kses_post($custom_body_html);
        } else {
            $body_html = $this->render_email_template($template_name, $context);
        }

        if ($body_html === '') {
            $fallback_text = nexdirectory_sanitize_textarea((string) ($context['fallback_text'] ?? ''));
            if ($fallback_text !== '') {
                if (!isset($context['email_heading']) || trim((string) $context['email_heading']) === '') {
                    $context['email_heading'] = $subject;
                }
                $body_html = $this->convert_plain_text_to_email_html($fallback_text);
            }
        }

        if ($body_html === '') {
            return '';
        }

        return $this->build_email_shell($subject, $body_html, $context);
    }

    /**
     * Core wrapper for wp_mail that handles HTML rendering and fallbacks.
     */
    public function send_platform_email($to, $subject, $template_name, array $context = [], array $headers = []) {
        $to = sanitize_email((string) $to);
        $subject = sanitize_text_field((string) $subject);
        
        if (!is_email($to) || $subject === '') {
            return false;
        }

        $body = $this->render_platform_email($subject, $template_name, $context);
        if ($body === '') {
            return false;
        }

        $has_content_type = false;
        foreach ((array) $headers as $header_line) {
            if (!is_string($header_line)) {
                continue;
            }
            if (stripos(trim($header_line), 'Content-Type:') === 0) {
                $has_content_type = true;
                break;
            }
        }
        if (!$has_content_type) {
            $headers[] = 'Content-Type: text/html; charset=UTF-8';
        }

        return wp_mail($to, $subject, $body, $headers);
    }

    /**
     * Centralized platform brand-name fallback chain.
     */
    private function get_platform_brand_name() {
        $brand_name = sanitize_text_field((string) get_option('nexdirectory_company_brand_name', ''));
        if ($brand_name === '') {
            $brand_name = sanitize_text_field((string) get_option('blogname', get_bloginfo('name')));
        }
        if ($brand_name === '') {
            $brand_name = __('Nex Directory', 'nexdirectory');
        }

        $brand_name = sanitize_text_field((string) apply_filters('nexdirectory_public_brand_name', $brand_name));
        return $brand_name !== '' ? $brand_name : __('Nex Directory', 'nexdirectory');
    }

    private function get_platform_brand_logo_url() {
        $candidates = [
            (string) get_option('nexdirectory_frontend_sticky_nav_logo_url', ''),
            (string) get_option('nexdirectory_frontend_footer_logo_url', ''),
        ];
        foreach ($candidates as $candidate) {
            $candidate = esc_url_raw($candidate);
            if ($candidate !== '') {
                return $candidate;
            }
        }
        if (function_exists('get_site_icon_url')) {
            $site_icon = esc_url_raw((string) get_site_icon_url(192));
            if ($site_icon !== '') {
                return $site_icon;
            }
        }
        return '';
    }

    private function convert_plain_text_to_email_html($text) {
        $text = nexdirectory_sanitize_textarea((string) $text);
        if ($text === '') {
            return '';
        }
        $text = str_replace(["\r\n", "\r"], "\n", $text);
        $paragraphs = preg_split("/\n{2,}/", (string) $text);
        if (!is_array($paragraphs)) {
            return '<p style="margin:0 0 14px;">' . nl2br(esc_html($text)) . '</p>';
        }

        $html = '';
        foreach ($paragraphs as $paragraph) {
            $paragraph = trim((string) $paragraph);
            if ($paragraph === '') {
                continue;
            }
            $html .= '<p style="margin:0 0 14px;">' . nl2br(esc_html($paragraph)) . '</p>';
        }
        return $html;
    }

    private function build_email_shell($subject, $content_html, array $context = []) {
        $brand_name = $this->get_platform_brand_name();
        $brand_logo_url = esc_url((string) ($context['brand_logo_url'] ?? $this->get_platform_brand_logo_url()));
        $site_url = esc_url(home_url('/'));
        $site_host = sanitize_text_field((string) wp_parse_url((string) $site_url, PHP_URL_HOST));
        if ($site_host === '') {
            $site_host = sanitize_text_field((string) home_url('/'));
        }

        $heading = sanitize_text_field((string) ($context['email_heading'] ?? ''));
        $preview_text = sanitize_text_field((string) ($context['preview_text'] ?? ''));
        if ($preview_text === '') {
            $preview_text = sanitize_text_field((string) wp_strip_all_tags((string) $subject));
        }
        if ($preview_text === '') {
            $preview_text = sanitize_text_field((string) wp_strip_all_tags((string) $brand_name));
        }
        if (function_exists('mb_substr')) {
            $preview_text = (string) mb_substr($preview_text, 0, 160);
        } else {
            $preview_text = (string) substr($preview_text, 0, 160);
        }

        $content_html = wp_kses_post((string) $content_html);
        $headline_html = $heading !== ''
            ? '<h1 style="margin:0 0 16px;font-size:24px;line-height:1.3;color:#0f172a;font-weight:700;">' . esc_html($heading) . '</h1>'
            : '';

        $logo_block_html = '';
        if ($brand_logo_url !== '') {
            $logo_block_html = '<span style="display:inline-block;background:#ffffff;padding:10px 14px;border-radius:12px;border:1px solid #dbe3ee;">'
                . '<img src="' . esc_url($brand_logo_url) . '" alt="' . esc_attr($brand_name) . '" style="display:block;max-width:220px;max-height:58px;width:auto;height:auto;border:0;outline:none;text-decoration:none;">'
                . '</span>';
        } else {
            $logo_block_html = '<div style="font-size:22px;line-height:1.2;font-weight:800;color:#0f172a;letter-spacing:0.2px;">' . esc_html($brand_name) . '</div>';
        }

        return '<!doctype html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head><body style="margin:0;padding:0;background:#f1f5f9;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#0f172a;">'
            . '<span style="display:none !important;visibility:hidden;mso-hide:all;opacity:0;color:transparent;height:0;width:0;overflow:hidden;">' . esc_html($preview_text) . '</span>'
            . '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background:#f1f5f9;padding:24px 12px;"><tr><td align="center">'
            . '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="max-width:680px;background:#0f172a;border-radius:14px 14px 0 0;"><tr><td style="padding:20px 24px;">'
            . '<a href="' . esc_url($site_url) . '" target="_blank" rel="noopener noreferrer" style="text-decoration:none;color:#ffffff;">' . $logo_block_html . '</a>'
            . '</td></tr></table>'
            . '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="max-width:680px;background:#ffffff;border:1px solid #e2e8f0;border-top:0;border-radius:0 0 14px 14px;overflow:hidden;"><tr><td style="padding:28px 24px 20px;">'
            . $headline_html
            . '<div style="font-size:15px;line-height:1.7;color:#334155;">' . $content_html . '</div>'
            . '</td></tr>'
            . '<tr><td style="padding:0 24px 22px;"><div style="height:1px;background:#e2e8f0;"></div></td></tr>'
            . '<tr><td style="padding:0 24px 24px;font-size:12px;line-height:1.6;color:#64748b;">'
            /* translators: 1: Placeholder value 1, 2: Placeholder value 2. */
            . esc_html(sprintf(__('Sent by %1$s via %2$s', 'nexdirectory'), $brand_name, $site_host))
            . '<br><a href="' . esc_url($site_url) . '" style="color:#0f172a;text-decoration:underline;">' . esc_html($site_host) . '</a>'
            . '</td></tr></table>'
            . '</td></tr></table></body></html>';
    }

    /**
     * Hooks into PHPMailer to apply custom SMTP settings if enabled in the platform.
     * Should be hooked to 'phpmailer_init'.
     */
    public function configure_phpmailer($phpmailer) {
        $from_email = sanitize_email((string) get_option('nexdirectory_smtp_from_email', ''));
        if (!is_email($from_email)) {
            $from_email = sanitize_email((string) get_option('admin_email', ''));
        }

        $from_name = sanitize_text_field((string) get_option('nexdirectory_smtp_from_name', ''));
        if ($from_name === '') {
            $from_name = $this->get_platform_brand_name();
        }

        try {
            // Apply configurable sender identity for all platform emails,
            // even when SMTP transport is not enabled.
            if ($from_email !== '' && is_email($from_email)) {
                $phpmailer->setFrom($from_email, $from_name, false);
            }

            if ((string) get_option('nexdirectory_smtp_enabled', '0') !== '1') {
                return;
            }

            $host = sanitize_text_field((string) get_option('nexdirectory_smtp_host', ''));
            if ($host === '') {
                return;
            }

            $port = absint((int) get_option('nexdirectory_smtp_port', 587));
            if ($port < 1) {
                $port = 587;
            }

            $encryption = strtolower(trim((string) get_option('nexdirectory_smtp_encryption', 'tls')));
            if ($encryption === 'none') {
                $encryption = '';
            }
            if (!in_array($encryption, ['', 'tls', 'ssl'], true)) {
                $encryption = 'tls';
            }

            $auth_enabled = (string) get_option('nexdirectory_smtp_auth', '1') === '1';
            $username = sanitize_text_field((string) get_option('nexdirectory_smtp_username', ''));
            $password = (string) get_option('nexdirectory_smtp_password', '');

            $phpmailer->isSMTP();
            $phpmailer->Host = $host;
            $phpmailer->Port = $port;
            $phpmailer->SMTPAuth = $auth_enabled;
            $phpmailer->SMTPSecure = $encryption;

            if ($auth_enabled) {
                $phpmailer->Username = $username;
                $phpmailer->Password = $password;
            }
        } catch (Exception $e) {
            if (method_exists($this->logger, 'append_runtime_log')) {
                $this->logger->append_runtime_log('warning', 'SMTP configuration failed', [
                    'message' => $e->getMessage(),
                ]);
            }
        }
    }

    /**
     * Replaces dynamic tokens (like {event_title}) inside an email subject string.
     */
    public function render_event_email_subject($template, $post_id, $status = '', array $extra_tokens = []) {
        $post_id = absint((int) $post_id);
        $template = sanitize_text_field((string) $template);
        $status = sanitize_text_field((string) $status);
        
        if ($template === '') {
            return '';
        }
        
        $token_map = [
            '{event_title}' => (string) get_the_title($post_id),
            '{event_date}' => (string) $this->date_helper->format_event_date($post_id),
            '{event_url}' => (string) get_permalink($post_id),
            '{listing_title}' => (string) get_the_title($post_id),
            '{listing_date}' => (string) $this->date_helper->format_event_date($post_id),
            '{listing_url}' => (string) get_permalink($post_id),
            '{status}' => (string) $status,
            '{listing_status}' => (string) $status,
        ];
        
        foreach ($extra_tokens as $token_key => $token_value) {
            $token_key = trim((string) $token_key);
            if ($token_key === '') {
                continue;
            }
            if ($token_key[0] !== '{') {
                $token_key = '{' . trim($token_key, '{}') . '}';
            }
            $token_map[$token_key] = sanitize_text_field((string) $token_value);
        }
        
        return strtr($template, $token_map);
    }

    /**
     * Replaces dynamic tokens inside an email body and formats it to safe HTML.
     */
    public function render_event_email_body($template, $post_id, $status = '', $note = '', array $extra_tokens = []) {
        $post_id = absint((int) $post_id);
        $template = (string) $template;
        $status = sanitize_text_field((string) $status);
        $note = nexdirectory_sanitize_textarea((string) $note);
        
        if ($template === '') {
            return '';
        }

        $token_map = [
            '{event_title}' => (string) get_the_title($post_id),
            '{event_date}' => (string) $this->date_helper->format_event_date($post_id),
            '{event_url}' => (string) get_permalink($post_id),
            '{listing_title}' => (string) get_the_title($post_id),
            '{listing_date}' => (string) $this->date_helper->format_event_date($post_id),
            '{listing_url}' => (string) get_permalink($post_id),
            '{status}' => (string) $status,
            '{listing_status}' => (string) $status,
            '{moderator_note}' => (string) $note,
        ];
        
        foreach ($extra_tokens as $token_key => $token_value) {
            $token_key = trim((string) $token_key);
            if ($token_key === '') {
                continue;
            }
            if ($token_key[0] !== '{') {
                $token_key = '{' . trim($token_key, '{}') . '}';
            }
            if (strpos($token_key, '_url}') !== false) {
                $token_map[$token_key] = esc_url_raw((string) $token_value);
            } else {
                $token_map[$token_key] = sanitize_text_field((string) $token_value);
            }
        }

        $rendered = strtr($template, $token_map);
        $rendered = trim((string) $rendered);
        if ($rendered === '') {
            return '';
        }

        // If the admin wrote plain text, convert newlines to <br> tags safely
        if (!preg_match('/<[^>]+>/', $rendered)) {
            return '<p>' . nl2br(esc_html($rendered)) . '</p>';
        }
        
        return wp_kses_post($rendered);
    }

    /**
     * Validates an email address against common disposable/spam domains.
     */
    public function valid_signup_email($email) {
        $email = sanitize_email((string) $email);
        if (!$email || !is_email($email)) {
            return false;
        }
        
        $domain = strtolower((string) substr(strrchr($email, '@'), 1));
        if ($domain === '' || strpos($domain, '.') === false) {
            return false;
        }
        
        $blocked = [
            'mailinator.com', 'tempmail.com', '10minutemail.com', 'guerrillamail.com', 'trashmail.com',
        ];
        if (in_array($domain, $blocked, true)) {
            return false;
        }
        
        if (function_exists('checkdnsrr') && !checkdnsrr($domain, 'MX') && !checkdnsrr($domain, 'A')) {
            return false;
        }
        
        return true;
    }
}
