<?php
if (! defined('ABSPATH')) {
    exit;
} class PufferGo_Contact_Form_Handler
{
    public const RATE_LIMIT_COUNT = 50;

    public const RATE_LIMIT_SECONDS = 300;

    public const MAX_FIELD_COUNT = 50;

    public const MAX_VALUE_LENGTH = 5000;

    public const MAX_ARRAY_ITEM_COUNT = 50;

    public const DAILY_LIMIT_DEFAULT = 100;

    public function __construct()
    {
        add_action('rest_api_init', array($this, 'register_api'));
        add_action('rest_api_init', array($this, 'register_admin_api'));

        if (is_admin()) {
            add_action('admin_enqueue_scripts', array($this, 'enqueue_inquiries_scripts'));
        }
    }

    public function create_table()
    {
        global $wpdb;
        $charset_collate = $wpdb->get_charset_collate();
        $table_name = $wpdb->prefix . 'puffergo_contact_submissions';
        $sql = "CREATE TABLE $table_name (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            form_data longtext NOT NULL,
            page_url varchar(500) DEFAULT '',
            ip_address varchar(45) DEFAULT '',
            user_agent text,
            status varchar(20) DEFAULT 'new',
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY idx_created_at (created_at),
            KEY idx_ip_address (ip_address)
        ) $charset_collate;";
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }

    public function register_api()
    {
        register_rest_route('puffergo/v1', '/contact', array('methods' => 'POST', 'callback' => array($this, 'handle_submission'), 'permission_callback' => '__return_true', ));
    }

    public function handle_submission($request)
    {
        $params = $request->get_json_params();
        $page_url = isset($params['page_url']) ? esc_url_raw($params['page_url']) : '';
        unset($params['page_url']);

        if (empty($params) || !is_array($params)) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Missing required fields.', 'puffergo')), 400);
        }

if (count($params) > self::MAX_FIELD_COUNT) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Submission too large.', 'puffergo')), 400);
        } $cleaned_data = array();

        foreach ($params as $key => $value) {
            $key = sanitize_key($key);

            if (is_array($value)) {
                if (count($value) > self::MAX_ARRAY_ITEM_COUNT) {
                    return new WP_REST_Response(array('success' => false, 'message' => __('Submission too large.', 'puffergo')), 400);
                }

foreach ($value as $item) {
                    if (is_string($item) && strlen($item) > self::MAX_VALUE_LENGTH) {
                        return new WP_REST_Response(array('success' => false, 'message' => __('Submission too large.', 'puffergo')), 400);
                    }
                } $cleaned_data[$key] = array_map('sanitize_text_field', $value);
            } else {
                if (is_string($value) && strlen($value) > self::MAX_VALUE_LENGTH) {
                    return new WP_REST_Response(array('success' => false, 'message' => __('Submission too large.', 'puffergo')), 400);
                } $cleaned_data[$key] = sanitize_text_field($value);
            }
        } $ip_address = $this->get_client_ip();

        if ($this->is_rate_limited($ip_address)) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Submission too frequent. Please try again later.', 'puffergo')), 429);
        } global $wpdb;
        $table = $wpdb->prefix . 'puffergo_contact_submissions';
        $table_exists = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table));

        if (empty($table_exists)) {
            $this->create_table();
        }

if ($this->is_daily_limit_reached()) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Daily submission limit reached. Please contact us by email instead.', 'puffergo')), 429);
        } $result = $wpdb->insert($table, array('form_data' => wp_json_encode($cleaned_data, JSON_UNESCAPED_UNICODE), 'page_url' => $page_url, 'ip_address' => $ip_address, 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '', 'status' => 'new', ), array('%s', '%s', '%s', '%s', '%s'));

        if ($result === false) {
            puffergo_log('Contact insert failed: ' . $wpdb->last_error . ' | SQL: ' . $wpdb->last_query, 'PufferGo-Contact');

            return new WP_REST_Response(array('success' => false, 'message' => __('System error.', 'puffergo')), 500);
        } $submission_id = $wpdb->insert_id;
        $admin_sent = $this->send_notification_email($submission_id, $cleaned_data, $page_url);
        $user_sent = $this->send_confirmation_email($cleaned_data, $page_url);

        return new WP_REST_Response(array('success' => true, 'message' => __('Submitted successfully.', 'puffergo'), 'data' => array('id' => $submission_id, 'admin_sent' => $admin_sent, 'user_sent' => $user_sent)), 200);
    }

    private function send_notification_email($id, $form_data, $url)
    {
        $to = get_option('puffergo_notification_emails', get_option('admin_email'));

        if (empty($to)) {
            return false;
        } $subject = sprintf(__('[%s] New form submission #%d', 'puffergo'), get_bloginfo('name'), $id);
        $message = '<h3>' . esc_html__('New contact form submission received', 'puffergo') . '</h3>';
        $message .= '<table border="1" cellpadding="5" cellspacing="0" style="border-collapse:collapse;">';

        foreach ($form_data as $key => $val) {
            $val_str = is_array($val) ? implode(', ', $val) : $val;
            $message .= sprintf('<tr><td><strong>%s</strong></td><td>%s</td></tr>', esc_html($key), esc_html($val_str));
        } $message .= '</table>';

        if (!empty($url)) {
            $message .= '<p>' . esc_html__('Source page:', 'puffergo') . ' <a href="' . esc_url($url) . '">' . esc_html($url) . '</a></p>';
        } $headers = array('Content-Type: text/html; charset=UTF-8');

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

    private function send_confirmation_email($form_data, $url)
    {
        $user_email = '';

        foreach (['email', 'user_email', 'your_email', 'mail'] as $field) {
            if (isset($form_data[$field]) && is_email($form_data[$field])) {
                $user_email = $form_data[$field];
                break;
            }
        }

if (empty($user_email)) {
            return false;
        } $subject = sprintf(__('Thank you for your inquiry - %s', 'puffergo'), get_bloginfo('name'));
        $message = '<div style="font-family: sans-serif; padding: 20px;">';
        $message .= '<h2>' . esc_html__('We have received your message', 'puffergo') . '</h2>';
        $message .= '<p>' . esc_html__('Thank you for contacting us. We will get back to you as soon as possible.', 'puffergo') . '</p>';
        $message .= '<hr>';
        $message .= '<h3>' . esc_html__('Copy of your submission:', 'puffergo') . '</h3>';
        $message .= '<ul>';

        foreach ($form_data as $key => $val) {
            $val_str = is_array($val) ? implode(', ', $val) : $val;

            if (in_array(strtolower($key), ['password', 'pwd'])) {
                continue;
            } $message .= sprintf('<li><strong>%s:</strong> %s</li>', esc_html($key), esc_html($val_str));
        } $message .= '</ul>';
        $message .= '<p style="color:#999; font-size:12px;">' . esc_html__('This email was sent automatically by the system.', 'puffergo') . '</p>';
        $message .= '</div>';
        $headers = array('Content-Type: text/html; charset=UTF-8');

        return wp_mail($user_email, $subject, $message, $headers);
    }

    private function is_rate_limited($ip_address)
    {
        global $wpdb;
        $time_threshold = gmdate('Y-m-d H:i:s', time() - self::RATE_LIMIT_SECONDS);
        $table_name = $wpdb->prefix . 'puffergo_contact_submissions';
        $count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE ip_address = %s AND created_at > %s", $ip_address, $time_threshold));

        return $count >= self::RATE_LIMIT_COUNT;
    }

    private function is_daily_limit_reached()
    {
        global $wpdb;
        $limit = (int) get_option('puffergo_contact_daily_limit', self::DAILY_LIMIT_DEFAULT);

        if ($limit <= 0) {
            return false;
        } $table_name = $wpdb->prefix . 'puffergo_contact_submissions';
        $today_start = gmdate('Y-m-d 00:00:00');
        $count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $table_name WHERE created_at >= %s", $today_start));

        if ($count < $limit) {
            return false;
        } $notice_flag = 'puffergo_contact_daily_limit_notified_' . gmdate('Y-m-d');

        if (! get_transient($notice_flag)) {
            set_transient($notice_flag, 1, DAY_IN_SECONDS);
            $to = get_option('puffergo_notification_emails', get_option('admin_email'));

            if (! empty($to)) {
                wp_mail($to, sprintf(__('[%s] Daily contact form limit reached', 'puffergo'), get_bloginfo('name')), sprintf(__('The contact form has received %1$d submissions today, reaching the daily limit of %2$d. Further submissions are being rejected until tomorrow. If this is unexpected traffic, please check the inquiries list for spam.', 'puffergo'), $count, $limit));
            }
        }

return true;
    }

    public static function render_inquiries_page()
    { ?>
        <div class="wrap">
            <div id="puffergo-inquiries-root"></div>
        </div>
        <?php
    }

    public function enqueue_inquiries_scripts($hook)
    {
        if ($hook !== 'puffergo_page_puffergo-inquiries') {
            return;
        } $plugin_url = plugin_dir_url(dirname(__FILE__));
        $asset_file = plugin_dir_path(dirname(__FILE__)) . 'build/blocks/inquiries-app/index.asset.php';

        if (file_exists($asset_file)) {
            $asset = include $asset_file;
            $dependencies = $asset['dependencies'];
            $version = $asset['version'];
        } else {
            $dependencies = array('wp-element', 'wp-components', 'wp-api-fetch', 'wp-data');
            $version = time();
        } wp_enqueue_script('puffergo-inquiries', $plugin_url . 'build/blocks/inquiries-app/index.js', $dependencies, $version, true);
        $style_file = plugin_dir_path(dirname(__FILE__)) . 'build/blocks/inquiries-app/style-index.css';

        if (file_exists($style_file)) {
            wp_enqueue_style('puffergo-inquiries-styles', $plugin_url . 'build/blocks/inquiries-app/style-index.css', array('puffergo-admin-tailwind', 'wp-components'), $version);
        } $tailwind_file = plugin_dir_path(dirname(__FILE__)) . 'build/blocks/inquiries-app/index.css';

        if (file_exists($tailwind_file)) {
            wp_enqueue_style('puffergo-inquiries-tailwind', $plugin_url . 'build/blocks/inquiries-app/index.css', array('puffergo-inquiries-styles'), $version);
        } wp_localize_script('puffergo-inquiries', 'puffergoInquiries', array('restUrl' => rest_url(), 'nonce' => wp_create_nonce('wp_rest'), ));
        wp_enqueue_style('wp-components');
    }

    public function register_admin_api()
    {
        register_rest_route('puffergo/v1', '/contact-submissions/stats', array('methods' => 'GET', 'callback' => array($this, 'get_submissions_stats'), 'permission_callback' => function () { return current_user_can('manage_options'); }, ));
        register_rest_route('puffergo/v1', '/contact-submissions', array('methods' => 'GET', 'callback' => array($this, 'get_submissions'), 'permission_callback' => function () { return current_user_can('manage_options'); }, ));
        register_rest_route('puffergo/v1', '/contact-submissions/(?P<id>\d+)', array('methods' => 'POST', 'callback' => array($this, 'delete_submission'), 'permission_callback' => function () { return current_user_can('manage_options'); }, ));
        register_rest_route('puffergo/v1', '/contact-submissions/(?P<id>\d+)/status', array('methods' => 'POST', 'callback' => array($this, 'update_submission_status'), 'permission_callback' => function () { return current_user_can('manage_options'); }, ));
    }

    public function get_submissions_stats($request)
    {
        global $wpdb;
        $search = sanitize_text_field($request->get_param('search') ?: '');
        $table = $wpdb->prefix . 'puffergo_contact_submissions';
        $where = '1=1';
        $params = array();

        if (! empty($search)) {
            $where .= ' AND form_data LIKE %s';
            $params[] = '%' . $wpdb->esc_like($search) . '%';
        } $status_counts = array('total' => 0, 'new' => 0, 'read' => 0, 'replied' => 0, );

        if (! empty($params)) {
            $counts = $wpdb->get_results($wpdb->prepare("SELECT status, COUNT(*) AS cnt FROM {$table} WHERE {$where} GROUP BY status", $params), ARRAY_A);
        } else {
            $counts = $wpdb->get_results("SELECT status, COUNT(*) AS cnt FROM {$table} GROUP BY status", ARRAY_A);
        }

foreach ($counts as $row) {
            $status_counts['total'] += (int) $row['cnt'];
            $status_counts[ $row['status'] ] = (int) $row['cnt'];
        }

return new WP_REST_Response($status_counts, 200);
    }

    public function get_submissions($request)
    {
        global $wpdb;
        $page = max(1, intval($request->get_param('page')));
        $per_page = max(1, min(100, intval($request->get_param('per_page') ?: 20)));
        $status = sanitize_key($request->get_param('status') ?: '');
        $search = sanitize_text_field($request->get_param('search') ?: '');
        $offset = ($page - 1) * $per_page;
        $table = $wpdb->prefix . 'puffergo_contact_submissions';
        $where = '1=1';
        $params = array();

        if (! empty($status) && in_array($status, array('new', 'read', 'replied'), true)) {
            $where .= ' AND status = %s';
            $params[] = $status;
        }

if (! empty($search)) {
            $where .= ' AND form_data LIKE %s';
            $params[] = '%' . $wpdb->esc_like($search) . '%';
        }

if (! empty($params)) {
            $total = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table} WHERE {$where}", $params));
            $items = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$table} WHERE {$where} ORDER BY created_at DESC LIMIT %d OFFSET %d", array_merge($params, array($per_page, $offset))), ARRAY_A);
        } else {
            $total = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$table} WHERE {$where}");
            $items = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$table} WHERE {$where} ORDER BY created_at DESC LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A);
        }

foreach ($items as &$item) {
            $item['form_data'] = json_decode($item['form_data'], true);
        } unset($item);

        return new WP_REST_Response(array('items' => $items, 'total' => $total, 'total_pages' => (int) ceil($total / $per_page), ), 200);
    }

    public function delete_submission($request)
    {
        global $wpdb;
        $id = intval($request['id']);
        $table = $wpdb->prefix . 'puffergo_contact_submissions';
        $deleted = $wpdb->delete($table, array('id' => $id), array('%d'));

        if (! $deleted) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Deletion failed or record not found.', 'puffergo'), ), 404);
        }

return new WP_REST_Response(array('success' => true, 'message' => __('Deleted.', 'puffergo'), ), 200);
    }

    public function update_submission_status($request)
    {
        global $wpdb;
        $id = intval($request['id']);
        $params = $request->get_json_params();
        $status = isset($params['status']) ? sanitize_key($params['status']) : '';

        if (! in_array($status, array('new', 'read', 'replied'), true)) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Invalid status value.', 'puffergo'), ), 400);
        } $table = $wpdb->prefix . 'puffergo_contact_submissions';
        $updated = $wpdb->update($table, array('status' => $status), array('id' => $id), array('%s'), array('%d'));

        if ($updated === false) {
            return new WP_REST_Response(array('success' => false, 'message' => __('Update failed.', 'puffergo'), ), 500);
        }

return new WP_REST_Response(array('success' => true, 'message' => __('Status updated.', 'puffergo'), ), 200);
    }

    private function get_client_ip()
    {
        $ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';

        return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '127.0.0.1';
    }
}
