<?php
declare(strict_types=1);
// ==================================================
// Nuclear Fancy Pants Edition™ -- NUCLEAR+++
// File: /home/ploi/automarketer-ai.com/public/wp-content/plugins/automarketer-ai/includes/class-comment-form.php
// Description: Frontend comment form with profanity filter, honeypot spam detection, IP rate limiting, and Comment Manager inbox integration - NUCLEAR+++
// Last Edited: 2026-05-15
// ==================================================

namespace AutoMarketerAI;

defined('ABSPATH') || exit;

class CommentForm
{
    // --------------------------------------------------
    // AJAX action for form submission.
    // --------------------------------------------------
    private const AJAX_ACTION = 'amai_submit_comment_form';

    // --------------------------------------------------
    // Register hooks.
    // --------------------------------------------------
    public static function register(): void
    {
        // enqueueAssets and appendForm are not used -- single.php handles asset loading and form rendering directly.
        add_action('wp_ajax_' . self::AJAX_ACTION,        [self::class, 'handleSubmit']);
        add_action('wp_ajax_nopriv_' . self::AJAX_ACTION, [self::class, 'handleSubmit']);
        add_filter('comments_open',  [self::class, 'suppressNativeComments'], 10, 2);
        add_filter('pings_open',    [self::class, 'suppressNativeComments'], 10, 2);
        add_filter('comments_array', [self::class, 'suppressNativeCommentsArray'], 10, 2);
    }

    // --------------------------------------------------
    // Enqueue frontend CSS and JS only on post/product
    // singles where the form is active.
    // --------------------------------------------------
    public static function enqueueAssets(): void
    {
        if (!self::isFormActive()) {
            return;
        }
        wp_enqueue_style(
            'amai-comment-form',
            AMAI_PLUGIN_URL . 'assets/css/amai-comment-form.css',
            [],
            (string) filemtime(AMAI_PLUGIN_DIR . 'assets/css/amai-comment-form.css')
        );
        wp_enqueue_script(
            'amai-comment-form',
            AMAI_PLUGIN_URL . 'assets/js/amai-comment-form.js',
            [],
            (string) filemtime(AMAI_PLUGIN_DIR . 'assets/js/amai-comment-form.js'),
            true
        );
        wp_localize_script('amai-comment-form', 'amaiCommentForm', [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'action'  => self::AJAX_ACTION,
            'nonce'   => wp_create_nonce(self::AJAX_ACTION),
            'postId'  => (string) get_the_ID(),
        ]);
    }

    // --------------------------------------------------
    // Append the comment form HTML after post content.
    // Only fires on the main query single post/product loop.
    // --------------------------------------------------
    public static function appendForm(string $content): string
    {
        if (!in_the_loop() || !is_main_query()) {
            return $content;
        }
        if (!self::isFormActive()) {
            return $content;
        }
        return $content . self::renderForm();
    }

    // --------------------------------------------------
    // Determine if the form is active for the current page.
    // --------------------------------------------------
    private static function isFormActive(): bool
    {
        if (is_single() && get_post_type() === 'post') {
            return get_option('amai_comment_form_posts_enabled') === '1';
        }
        if (is_singular('product')) {
            return get_option('amai_comment_form_products_enabled') === '1';
        }
        return false;
    }

    // --------------------------------------------------
    // Render the comment form HTML.
    // Honeypot field: #amai-cf-website (hidden via CSS).
    // --------------------------------------------------
    private static function renderForm(): string
    {
        $post_type = get_post_type();
        $label     = ($post_type === 'product') ? 'Leave a Review' : 'Leave a Comment';
        $btn_label = ($post_type === 'product') ? 'Submit Review' : 'Post Comment';

        ob_start();
        ?>
        <div class="amai-comment-form-wrap" id="amai-comment-form-wrap">
            <h3 class="amai-comment-form-title"><?php echo esc_html($label); ?></h3>
            <div class="amai-comment-form-fields">
                <div class="amai-cf-row amai-cf-row--two">
                    <div class="amai-cf-field">
                        <label class="amai-cf-label" for="amai-cf-name">Name <span class="amai-cf-required">*</span></label>
                        <input class="amai-cf-input" type="text" id="amai-cf-name" name="amai_cf_name" autocomplete="name" maxlength="100" required />
                    </div>
                    <div class="amai-cf-field">
                        <label class="amai-cf-label" for="amai-cf-email">Email <span class="amai-cf-required">*</span></label>
                        <input class="amai-cf-input" type="email" id="amai-cf-email" name="amai_cf_email" autocomplete="email" maxlength="200" required />
                    </div>
                </div>
                <div class="amai-cf-field">
                    <label class="amai-cf-label" for="amai-cf-content">Comment <span class="amai-cf-required">*</span></label>
                    <textarea class="amai-cf-textarea" id="amai-cf-content" name="amai_cf_content" rows="5" maxlength="2000" required></textarea>
                </div>
                <div class="amai-cf-honeypot" aria-hidden="true">
                    <label for="amai-cf-website">Website</label>
                    <input type="text" id="amai-cf-website" name="amai_cf_website" tabindex="-1" autocomplete="off" />
                </div>
                <div class="amai-cf-actions">
                    <button type="button" class="amai-cf-submit" id="amai-cf-submit"><?php echo esc_html($btn_label); ?></button>
                </div>
                <div class="amai-cf-notice" id="amai-cf-notice" aria-live="polite"></div>
            </div>
        </div>
        <?php
        return (string) ob_get_clean();
    }

    // --------------------------------------------------
    // AJAX handler: validate, filter, rate-limit, insert.
    // --------------------------------------------------
    public static function handleSubmit(): void
    {
        // Nonce check.
        $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash((string) $_POST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, self::AJAX_ACTION)) {
            wp_send_json_error(['message' => 'Security check failed. Please reload and try again.'], 403);
        }

        // Honeypot: if filled, silently succeed (don't tell the bot).
        $honeypot = isset($_POST['amai_cf_website']) ? (string) $_POST['amai_cf_website'] : '';
        if ($honeypot !== '') {
            wp_send_json_success(['message' => 'Your comment has been submitted.']);
        }

        // Post ID.
        $post_id = isset($_POST['post_id']) ? (int) $_POST['post_id'] : 0;
        if ($post_id <= 0) {
            wp_send_json_error(['message' => 'Invalid submission.'], 400);
        }
        $post = get_post($post_id);
        if (!$post instanceof \WP_Post || !in_array($post->post_status, ['publish'], true)) {
            wp_send_json_error(['message' => 'Invalid submission.'], 400);
        }

        // Verify form is enabled for this post type.
        $post_type = get_post_type($post_id);
        if ($post_type === 'post' && get_option('amai_comment_form_posts_enabled') !== '1') {
            wp_send_json_error(['message' => 'Comments are not enabled.'], 403);
        }
        if ($post_type === 'product' && get_option('amai_comment_form_products_enabled') !== '1') {
            wp_send_json_error(['message' => 'Reviews are not enabled.'], 403);
        }
        if (!in_array($post_type, ['post', 'product'], true)) {
            wp_send_json_error(['message' => 'Invalid submission.'], 400);
        }

        // Input sanitization.
        $name    = isset($_POST['amai_cf_name'])    ? sanitize_text_field(wp_unslash((string) $_POST['amai_cf_name']))    : '';
        $email   = isset($_POST['amai_cf_email'])   ? sanitize_email(wp_unslash((string) $_POST['amai_cf_email']))        : '';
        $content = isset($_POST['amai_cf_content']) ? sanitize_textarea_field(wp_unslash((string) $_POST['amai_cf_content'])) : '';

        if ($name === '' || $email === '' || $content === '') {
            wp_send_json_error(['message' => 'Please fill in all required fields.'], 400);
        }
        if (!is_email($email)) {
            wp_send_json_error(['message' => 'Please enter a valid email address.'], 400);
        }
        if (strlen($content) < 10) {
            wp_send_json_error(['message' => 'Your comment is too short.'], 400);
        }

        // Rate limit check.
        $ip      = self::hashIp(self::getIp());
        $limit   = max(1, (int) get_option('amai_comment_form_rate_limit', '10'));
        if (self::isRateLimited($ip, $post_id, $limit)) {
            wp_send_json_error(['message' => 'You have submitted too many comments recently. Please try again later.'], 429);
        }

        // Profanity filter.
        $profanity_hit = self::checkProfanity($content . ' ' . $name);
        if ($profanity_hit !== '') {
            wp_send_json_error(['message' => 'Your comment contains language that is not allowed. Please revise and try again.'], 400);
        }

        // Determine moderation status based on reply mode.
        $mode_option = ($post_type === 'product') ? 'amai_comment_form_reply_mode_products' : 'amai_comment_form_reply_mode_posts';
        $mode        = (string) get_option($mode_option, 'manual');
        $channel     = ($post_type === 'product') ? 'woocommerce' : 'wordpress';

        // Log rate limit entry.
        self::logSubmission($ip, $post_id);

        // Store directly in wp_amai_social_comments -- skip wp_insert_comment().
        // Keeps comments out of the native WP comments section entirely.
        // Native WP comments resume automatically when the form is disabled.
        $platform_comment_id = 'cf_' . gmdate('YmdHis') . '_' . substr(hash('sha256', $name . $email . $content), 0, 8);
        $platform_post_id    = (string) $post_id;

        global $wpdb;
        $table = $wpdb->prefix . 'amai_social_comments';

        $existing = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT id FROM `{$table}` WHERE channel = %s AND platform_comment_id = %s LIMIT 1",
                $channel,
                $platform_comment_id
            )
        );

        if ($existing === 0) {
            $wpdb->query(
                $wpdb->prepare(
                    "INSERT INTO `{$table}`
                        (channel, platform_comment_id, platform_post_id, parent_platform_comment_id,
                         author_name, author_platform_id, content, commented_at,
                         status, is_followup, reply_to_comment_id, wp_comment_id)
                     VALUES (%s, %s, %s, %s, %s, %s, %s, %s, 'new', 0, NULL, NULL)",
                    $channel,
                    $platform_comment_id,
                    $platform_post_id,
                    '',
                    $name,
                    $email,
                    $content,
                    gmdate('Y-m-d H:i:s')
                )
            );
            $inbox_id = (int) $wpdb->insert_id;
            if ($inbox_id > 0) {
                CommentResponder::handleNew($inbox_id);
            }
        }

        // Add commenter to Elastic Email blog-commenter segment if logged out
        // and email does not match any existing client contact.
        if (!is_user_logged_in()) {
            self::syncBlogCommenterToElasticEmail($name, $email);
        }

        $message = ($approved === 0)
            ? 'Thank you! Your comment is awaiting moderation.'
            : 'Thank you for your comment!';

        wp_send_json_success(['message' => $message]);
    }

    // --------------------------------------------------
    // Sync a blog commenter to Elastic Email with the blog-commenter tag.
    // Skipped if: EE not active, no API key, or email already in wp_amai_email_contacts.
    // --------------------------------------------------
    private static function syncBlogCommenterToElasticEmail(string $name, string $email): void
    {
        if ($email === '') {
            return;
        }

        // Check email not already a client contact.
        global $wpdb;
        $table  = $wpdb->prefix . 'amai_email_contacts';
        $exists = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM `{$table}` WHERE email = %s",
                strtolower($email)
            )
        );
        if ($exists > 0) {
            return;
        }

        // Check Elastic Email is active.
        $active_modules = (array) get_option('amai_active_modules', []);
        if (!in_array('email-elastic', $active_modules, true)) {
            return;
        }

        $api_key_enc = (string) get_option('amai_api_key_email-elastic', '');
        if ($api_key_enc === '') {
            return;
        }
        $api_key = \AutoMarketerAI\KeyVault::decrypt($api_key_enc);
        if ($api_key === '') {
            return;
        }

        // Parse name into first/last.
        $parts      = explode(' ', trim($name), 2);
        $first_name = $parts[0] ?? '';
        $last_name  = $parts[1] ?? '';

        $payload = [
            'Email'     => $email,
            'FirstName' => $first_name,
            'LastName'  => $last_name,
            'Tags'      => ['blog-commenter'],
            'Status'    => 'Active',
        ];

        wp_remote_post(
            'https://api.elasticemail.com/v4/contacts',
            [
                'timeout' => 10,
                'headers' => [
                    'X-ElasticEmail-ApiKey' => $api_key,
                    'Content-Type'          => 'application/json',
                ],
                'body' => wp_json_encode($payload),
            ]
        );
        // We intentionally do not block the comment submission on EE API failure.
    }

    // --------------------------------------------------
    // Check if IP has exceeded the rate limit in the last hour.
    // --------------------------------------------------
    private static function isRateLimited(string $ip_hash, int $post_id, int $limit): bool
    {
        global $wpdb;
        $table    = $wpdb->prefix . 'amai_comment_form_rate_limit';
        $since    = gmdate('Y-m-d H:i:s', time() - 3600);
        $count    = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM `{$table}` WHERE ip_hash = %s AND submitted_at >= %s",
                $ip_hash,
                $since
            )
        );
        return $count >= $limit;
    }

    // --------------------------------------------------
    // Log a rate limit entry for this IP and post.
    // Also prunes entries older than 2 hours.
    // --------------------------------------------------
    private static function logSubmission(string $ip_hash, int $post_id): void
    {
        global $wpdb;
        $table = $wpdb->prefix . 'amai_comment_form_rate_limit';
        $now   = gmdate('Y-m-d H:i:s');
        $wpdb->query(
            $wpdb->prepare(
                "INSERT INTO `{$table}` (ip_hash, post_id, submitted_at) VALUES (%s, %d, %s)",
                $ip_hash,
                $post_id,
                $now
            )
        );
        // Prune old entries.
        $cutoff = gmdate('Y-m-d H:i:s', time() - 7200);
        $wpdb->query(
            $wpdb->prepare(
                "DELETE FROM `{$table}` WHERE submitted_at < %s",
                $cutoff
            )
        );
    }

    // --------------------------------------------------
    // Check comment + author name against the profanity wordlist.
    // Returns the matched word or empty string if clean.
    // --------------------------------------------------
    private static function checkProfanity(string $text): string
    {
        $raw   = (string) get_option('amai_comment_profanity_words', '');
        if ($raw === '') {
            return '';
        }
        $words = array_filter(array_map('trim', explode("\n", strtolower($raw))));
        $lower = strtolower($text);
        foreach ($words as $word) {
            if ($word === '') {
                continue;
            }
            // Word boundary match to avoid false positives (e.g. "ass" in "class").
            if (preg_match('/\b' . preg_quote($word, '/') . '\b/', $lower)) {
                return $word;
            }
        }
        return '';
    }

    // --------------------------------------------------
    // Get the submitter's real IP address.
    // --------------------------------------------------
    private static function getIp(): string
    {
        $candidates = [
            $_SERVER['HTTP_CF_CONNECTING_IP'] ?? '',
            $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '',
            $_SERVER['REMOTE_ADDR'] ?? '',
        ];
        foreach ($candidates as $candidate) {
            $ip = trim(explode(',', $candidate)[0]);
            if (filter_var($ip, FILTER_VALIDATE_IP) !== false) {
                return $ip;
            }
        }
        return '0.0.0.0';
    }

    // --------------------------------------------------
    // Suppress native WP comment form on posts where our form is active.
    // --------------------------------------------------
    public static function suppressNativeComments(bool $open, int $post_id): bool
    {
        if (!$open) {
            return $open;
        }
        $post_type = get_post_type($post_id);
        if ($post_type === 'post' && get_option('amai_comment_form_posts_enabled') === '1') {
            return false;
        }
        if ($post_type === 'product' && get_option('amai_comment_form_products_enabled') === '1') {
            return false;
        }
        return $open;
    }

    // --------------------------------------------------
    // Return empty comments array to prevent native list rendering.
    // --------------------------------------------------
    public static function suppressNativeCommentsArray(array $comments, int $post_id): array
    {
        $post_type = get_post_type($post_id);
        if ($post_type === 'post' && get_option('amai_comment_form_posts_enabled') === '1') {
            return [];
        }
        if ($post_type === 'product' && get_option('amai_comment_form_products_enabled') === '1') {
            return [];
        }
        return $comments;
    }

    // --------------------------------------------------
    // Hash an IP for storage -- never store raw IPs.
    // --------------------------------------------------
    private static function hashIp(string $ip): string
    {
        return hash('sha256', $ip . (defined('AUTH_SALT') ? AUTH_SALT : 'amai-salt'));
    }
}