<?php

namespace EstatebudConnect\Controllers;

if (!defined('WPINC')) {
    die();
}

use EstatebudConnect\Plugin;
use EstatebudConnect\Configs\App;
use EstatebudConnect\Core\Strings;
use EstatebudConnect\Core\Cache;
use EstatebudConnect\Core\Log;
use EstatebudConnect\Models\Property;
use EstatebudConnect\Models\Project;
use EstatebudConnect\Models\Forms;
use EstatebudConnect\Models\Field;
use EstatebudConnect\Models\Settings;
use EstatebudConnect\Services\Captcha;
use EstatebudConnect\Traits\Singleton;
use EstatebudConnect\Utilities\Helper;
use EstatebudConnect\Models\SearchExperience;
use EstatebudConnect\Services\Estatebud;

class Form
{
    use Singleton;

    public function __construct()
    {
        add_action('wp_ajax_estatebud_submit_contact_form_data', [$this, 'submit_contact_form_data']);
        add_action('wp_ajax_nopriv_estatebud_submit_contact_form_data', [$this, 'submit_contact_form_data']);
        add_action('wp_ajax_estatebud_get_share_agent_modal', [$this, 'get_share_agent_modal']);
        add_action('wp_ajax_nopriv_estatebud_get_share_agent_modal', [$this, 'get_share_agent_modal']);
    }

    public function enqueue_assets()
    {
        $settings_data = Settings::instance()->get_data();
        $captcha_provider = $settings_data['captcha_provider'];
        $captcha_site_key = $settings_data['captcha_site_key'] ?? '';

        if (Plugin::has_build_tools()) {
            wp_enqueue_script(App::SLUG . '-frontend', Helper::get_url('app/Javascript/public/index.js'), [App::SLUG . '-choices', App::SLUG . '-intltel'], uniqid());
        } else {
            wp_enqueue_script(App::SLUG . '-frontend', Helper::get_url('dist/bundle-main.js'), [App::SLUG . '-choices', App::SLUG . '-intltel'], App::VERSION);
        }

        if (!empty($captcha_provider) && !empty($captcha_site_key)) {
            if ($captcha_provider === 'recaptcha') {
                wp_enqueue_script(
                    App::SLUG . '-recaptcha',
                    'https://recaptcha.net/recaptcha/api.js?render=' . esc_attr($captcha_site_key),
                    [],
                    null,
                );
            } elseif ($captcha_provider === 'hcaptcha') {
                wp_enqueue_script(SLUG . '-hcaptcha', 'https://js.hcaptcha.com/1/api.js', [], null);
            } elseif ($captcha_provider === 'turnstile') {
                wp_enqueue_script(
                    App::SLUG . '-turnstile',
                    'https://challenges.cloudflare.com/turnstile/v0/api.js',
                    [],
                    null,
                );
            }
        }

        Strings::init_defaults('frontend');
    }

    public function render_form($form_id, $context = [])
    {
        $settings_data = Settings::instance()->get_data();
        $form_data = Forms::instance()->get_form($form_id);

        if (!$form_data) {
            return '<div class="estatebud-form-not-found-message">Form "' . esc_html($form_id) . '" not found</div>';
        }

        $form_type = $form_data['type'] ?? '';

        if ($form_type === 'contact') {
            $field_options = Estatebud::instance()
                ->cache(Cache::TTL_1MO)
                ->get_fields(['component' => 'property']);

            $this->enqueue_assets();

            ob_start();
            Helper::render_markup_from_views('Public/Form/form.php', [
                'form_id' => $form_id,
                'settings_data' => $settings_data,
                'form_data' => $form_data,
                'field_options' => $field_options,
            ]);

            return ob_get_clean();
        }

        $this->enqueue_assets();

        $filter_vars = $this->get_filter_header_vars($form_id, $form_data, $context);

        ob_start();
        Helper::render_markup_from_views('Public/Form/filter-header.php', $filter_vars);
        $html = ob_get_clean();

        return '<div class="estatebud-form">'.$html.'</div>';
    }

    private function get_filter_header_vars($form_id, $form_data, $context)
    {
        $shortcode_id = $context['shortcode_id'] ?? uniqid();
        $search_id = $context['search_id'] ?? '';
        $listing_type = ($form_data['type'] ?? '') === 'project-search' ? 'project' : 'property';

        return [
            'form_id' => $form_id,
            'form_data' => $form_data,
            'shortcode_id' => $shortcode_id,
            'search_id' => $search_id,
            'query_from_link' => $context['query_from_link'] ?? [],
            'settings_data' => Settings::instance()->get_data(),
            'field_options' => Estatebud::instance()->cache(Cache::TTL_1MO)->get_fields(['component' => $listing_type]),
            'location_options' => Estatebud::instance()->cache(Cache::TTL_5M)->get_property_areas(),
            'search_exp_data' => !empty($search_id) ? SearchExperience::instance()->get_search_exp($search_id) : null,
        ];
    }

    public function submit_contact_form_data()
    {
        if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'estatebud-nonce')) {
            wp_send_json_error(
                [
                    'message' => 'Nonce verification failed',
                    'code' => 403,
                ],
                403,
            );
        }

        Log::write('Form: Processing submission', $_POST);

        $form_id = sanitize_text_field(wp_unslash($_POST['form_id'] ?? ''));
        $form_data = Forms::instance()->get_form($form_id);
        $field_options = Estatebud::instance()
                ->cache(Cache::TTL_1MO)
                ->get_fields(['component' => 'property']);

        Log::write('Form: Configuration', $form_data);

        if (!$form_data) {
            wp_send_json_error(
                [
                    'message' => sprintf('Form with "%s" not found', $form_id),
                    'code' => 404,
                ],
                404,
            );
        }

        $listing_type = sanitize_text_field(wp_unslash($_POST['listing_type'] ?? ''));
        $listing_id = sanitize_text_field(wp_unslash($_POST['listing_id'] ?? ''));

        $email_to = $form_data['email_to'];
        $email_subject = $form_data['email_subject'];
        $email_message = $form_data['email_message'];
        $email_from = $form_data['email_from'];
        $email_from_name = $form_data['email_from_name'];
        $email_reply_to = $form_data['email_reply_to'];
        $email_cc = $form_data['email_cc'];
        $email_bcc = $form_data['email_bcc'];
        $email_meta_data = $form_data['email_meta_data'];

        $confirmation_email_subject = Helper::term("form.{$form_id}.confirmation_email.subject");
        $confirmation_email_message = Helper::term("form.{$form_id}.confirmation_email.message");
        $confirmation_email_from = $form_data['confirmation_email_from'];
        $confirmation_email_from_name = $form_data['confirmation_email_from_name'];
        $confirmation_email_reply_to = $form_data['confirmation_email_reply_to'];
        $confirmation_email_cc = $form_data['confirmation_email_cc'];
        $confirmation_email_bcc = $form_data['confirmation_email_bcc'];

        $fields = $form_data['fields'];
        $field_values = [];
        $field_validation = [];

        foreach ($fields as $field) {
            $field_obj = new Field($field);
            $name = $field_obj->get_name();
            $options = $field_obj->get_options();
            $raw_value = wp_unslash($_POST[$name] ?? '');
            $raw_values = explode('|', $raw_value);

            $matching_api_field = null;
            foreach ($field_options as $option) {
                if (isset($option['name']) && $option['name'] === $name && empty($field_obj->get_raw_options())) {
                    $matching_api_field = $option;
                    break;
                }
            }

            $validation_result = $field_obj->validate_value($raw_value);
            if ($validation_result !== true) {
                $field_validation[$name] = $validation_result;
            }

            if ($field_obj->is_type('phone') && isset($_POST[$field_obj->get_name() . '_dial_code'])) {
                $raw_value = '+' . $_POST[$field_obj->get_name() . '_dial_code'] . ' ' . $raw_value;
            }

            if ($field_obj->is_type('phone') && isset($_POST[$field_obj->get_name() . '_country'])) {
                $raw_value = strtoupper('[' . $_POST[$field_obj->get_name() . '_country'] . '] ') . $raw_value;
            }

            if (count($raw_values) > 0 && in_array($field_obj->get_type(), ['checkbox','select'])) {
                $selected_options = [];

                foreach ($raw_values as $value) {
                    if ($matching_api_field) {
                        foreach ($matching_api_field['options'] as $option) {
                            if (isset($option['value']) && $option['value'] === $value) {
                                $selected_options[] = $option['label'];
                            }
                        }
                    } else {
                        foreach ($options as $option) {
                            if (isset($option['value']) && $option['value'] === $value) {
                                $selected_options[] = $option['label'];
                            }
                        }
                    }
                }
                
                $raw_value = $selected_options;
            }

            $value = $field_obj->sanitize_value($raw_value);

            if ($value) {
                if ($field_obj->is_type('email')) {
                    $submitter_email = $value;
                }

                $label = $field_obj->get_display_name();

                $field_values[$name] = [
                    'id' => $field_obj->get_id(),
                    'type' => $field_obj->get_type(),
                    'name' => $name,
                    'value' => is_array($value) ? implode(', ', $value) : $value,
                    'label' => $label,
                    'crm_field' => $field_obj->get_crm_field(),
                ];
            }
        }

        if (count($field_validation)) {
            Log::write('Form: Validation failed', $field_validation);

            wp_send_json_error(
                [
                    'message' => 'Form validation failed',
                    'code' => 400,
                    'data' => $field_validation,
                ],
                400,
            );
        }

        $captcha_result = Captcha::instance()->post_captcha_response();

        Log::write('Form: Captcha', $captcha_result);

        if ($captcha_result['success'] === false) {
            wp_send_json_error(
                [
                    'message' => 'Captcha verification failed',
                    'code' => 400,
                    'data' => 'captcha',
                ],
                400,
            );
        }

        if (!empty($listing_type) && !empty($listing_id)) {
            try {
                if ($listing_type === 'project') {
                    $listing_raw = Estatebud::instance()->get_project($listing_id);
                    $listing = new Project($listing_raw);
                } else {
                    $listing_raw = Estatebud::instance()->get_property($listing_id);
                    $listing = new Property($listing_raw);
                }
            } catch (\Exception $e) {
                Log::write('Form: Listing not found', [
                    'listing_type' => $listing_type,
                    'listing_id' => $listing_id,
                ]);
            }
        }

        $fields_placeholder = '{{ form.fields }}';

        if (empty($email_message)) {
            $email_message = $fields_placeholder;
        }

        if (str_contains($email_message, $fields_placeholder)) {
            $all_fields = [];

            foreach ($field_values as $field) {
                $all_fields[] = '<strong>' . esc_html($field['label']) . ':</strong> ' . esc_html($field['value']);
            }

            $all_fields = implode("\r\n", $all_fields);

            $email_message = str_replace($fields_placeholder, $all_fields, $email_message);
            $confirmation_email_message = str_replace($fields_placeholder, $all_fields, $confirmation_email_message);
        }

        foreach ($field_values as $field) {
            $field_placeholder = sprintf('{{ field.%s }}', $field['id']);
            $field_value = esc_html($field['value']);

            $email_subject = str_replace($field_placeholder, $field_value, $email_subject);
            $email_message = str_replace($field_placeholder, $field_value, $email_message);
            $confirmation_email_subject = str_replace($field_placeholder, $field_value, $confirmation_email_subject);
            $confirmation_email_message = str_replace($field_placeholder, $field_value, $confirmation_email_message);
        }

        $meta_data_values = [];

        foreach ($email_meta_data as $meta_data) {
            if ($meta_data === 'date') {
                $datetime = gmdate('j F Y');
                $meta_data_values[] = '<strong>Date:</strong> ' . $datetime;
            }
            if ($meta_data === 'time') {
                $time = gmdate('H:i');
                $meta_data_values[] = '<strong>Time:</strong> ' . $time;
            }
            if ($meta_data === 'ip') {
                $user_ip = Helper::get_user_ip();
                $meta_data_values[] = '<strong>IP:</strong> ' . esc_html($user_ip);
            }
            if ($meta_data === 'browser') {
                $meta_data_values[] = '<strong>Browser:</strong> ' . esc_html(sanitize_text_field(wp_unslash($_POST['browser_info'] ?? 'Unknown')));
            }
            if ($meta_data === 'page_url') {
                $meta_data_values[] = '<strong>Page URL:</strong> ' . esc_html(sanitize_text_field(wp_unslash($_POST['page_url'] ?? 'Unknown')));
            }
        }

        if (count($meta_data_values)) {
            $meta_data_values = implode("\r\n", $meta_data_values);
            $email_message .= "\r\n\r\n<strong>Meta data</strong>\r\n" . $meta_data_values;
        }

        $email_headers = ['Content-Type: text/html; charset=UTF-8', "From: $email_from_name <$email_from>"];

        if (!empty($email_reply_to)) {
            $email_headers[] = "Reply-To: $email_reply_to";
        }

        $email_cc_recipients = Helper::email_addresses_to_array($email_cc);
        foreach ($email_cc_recipients as $email_cc_recipient) {
            $email_headers[] = "CC: $email_cc_recipient";
        }

        $email_bcc_recipients = Helper::email_addresses_to_array($email_bcc);
        foreach ($email_bcc_recipients as $email_bcc_recipient) {
            $email_headers[] = "BCC: $email_bcc_recipient";
        }

        $confirmation_email_headers = [
            'Content-Type: text/html; charset=UTF-8',
            "From: $confirmation_email_from_name <$confirmation_email_from>",
        ];

        if (!empty($confirmation_email_reply_to)) {
            $confirmation_email_headers[] = "Reply-To: $confirmation_email_reply_to";
        }

        $confirmation_email_cc_recipients = Helper::email_addresses_to_array($confirmation_email_cc);
        foreach ($confirmation_email_cc_recipients as $confirmation_email_cc_recipient) {
            $confirmation_email_headers[] = "CC: $confirmation_email_cc_recipient";
        }

        $confirmation_email_bcc_recipients = Helper::email_addresses_to_array($confirmation_email_bcc);
        foreach ($confirmation_email_bcc_recipients as $confirmation_email_bcc_recipient) {
            $confirmation_email_headers[] = "BCC: $confirmation_email_bcc_recipient";
        }

        $result_admin_mail = false;
        $result_user_mail = false;

        $email_to_recipients = Helper::email_addresses_to_array($email_to);

        if (count($email_to_recipients) == 0) {
            $admin_users = get_users('role=Administrator');
            foreach ($admin_users as $admin_user) {
                $email_to_recipients[] = $admin_user->user_email;
            }
        }

        if (count($email_to_recipients) > 0) {
            $result_admin_mail = wp_mail($email_to_recipients, $email_subject, nl2br($email_message), $email_headers);
        }

        if (isset($submitter_email)) {
            $result_user_mail = wp_mail(
                $submitter_email,
                $confirmation_email_subject,
                nl2br($confirmation_email_message),
                $confirmation_email_headers,
            );
        }

        $pipeline_stage_id = $form_data['pipeline_stage_id'];

        if (!empty($pipeline_stage_id)) {
            $pipelines = Estatebud::instance()->cache(Cache::TTL_1H)->get_pipelines();
            foreach ($pipelines as $pipeline) {
                $pipeline_id = $pipeline['id'];
                $pipeline_stages = $pipeline['stages'] ?? [];

                foreach ($pipeline_stages as $pipeline_stage) {
                    if ($pipeline_stage['id'] == $pipeline_stage_id) {
                        $create_crm_deal = true;
                        break;
                    }
                }
            }

            if (isset($create_crm_deal)) {
                $deal_payload = [];

                foreach ($field_values as $field) {
                    if ($field['crm_field'] == 'name' || (in_array($field['name'], ['name', 'fullname', 'full_name']) && !isset($deal_payload['name']))) {
                        $deal_payload['name'] = $field['value'];
                    }
                    if ($field['crm_field'] == 'first_name' || (in_array($field['name'], ['firstname', 'first_name', 'given_name']) && !isset($deal_payload['first_name']))) {
                        $deal_payload['first_name'] = $field['value'];
                    }
                    if ($field['crm_field'] == 'last_name' || (in_array($field['name'], ['lastname', 'last_name', 'surname']) && !isset($deal_payload['last_name']))) {
                        $deal_payload['last_name'] = $field['value'];
                    }

                    if (($field['crm_field'] == 'mobile' || in_array($field['name'], ['mobile'])) && $field['type'] === 'phone') {
                        $parts = explode(" ", $field['value'], 3);

                        $deal_payload['mobile_call_code'] = str_replace(["[","]"], '', $parts[0] ?? $parts[1] ?? '');
                        $deal_payload['mobile'] = $parts[2];
                    }

                    if (($field['crm_field'] == 'phone' || in_array($field['name'], ['phone'])) && $field['type'] === 'phone') {
                        $parts = explode(" ", $field['value'], 3);

                        $deal_payload['phone_call_code'] = str_replace(["[","]"], '', $parts[0] ?? $parts[1] ?? '');
                        $deal_payload['phone'] = $parts[2];
                    }
                }

                $deal_payload['note'] = strip_tags($email_message);

                if (isset($submitter_email)) {
                    $deal_payload['email'] = $submitter_email;
                }

                if (isset($listing)) {
                    $deal_payload['property_id'] = $listing->get_id();

                    $listing_price = $listing->get_price();

                    if ($listing_price['price'] > 0) {
                        $deal_payload['value'] = $listing_price['price'];
                        $deal_payload['currency'] = $listing_price['currency'];
                    }
                }

                $deal_result = Estatebud::instance()
                    ->new_deal($pipeline_id, $pipeline_stage_id, $deal_payload);
            }
        }

        if ($result_admin_mail) {
            Log::write('Form: Successfully submitted', [
                'to' => $email_to,
                'result' => $result_admin_mail,
                'form_data' => $form_data,
                'deal_data' => $deal_payload ?? [],
                'deal_result' => $deal_result ?? [],
            ]);

            wp_send_json_success(
                [
                    'message' => 'Form submission successful',
                    'code' => 200,
                    'data' => 'success',
                ],
                200,
            );
        } else {
            Log::write('Form: Submission failed', [
                'to' => $email_to,
                'result' => $result_admin_mail,
                'form_data' => $form_data,
                'deal_data' => $deal_payload ?? [],
                'deal_result' => $deal_result ?? [],
            ]);

            wp_send_json_error(
                [
                    'message' => 'Form submission failed',
                    'code' => 500,
                    'data' => 'submit',
                ],
                500,
            );
        }
    }

    public function get_share_agent_modal()
    {
        if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'estatebud-nonce')) {
            wp_send_json_error(
                [
                    'message' => 'Nonce verification failed',
                    'code' => 403,
                ],
                403,
            );
        }

        $form_id = sanitize_text_field(wp_unslash($_POST['form_id'] ?? ''));
        $form_data = Forms::instance()->get_form($form_id);

        if (!$form_data) {
            wp_send_json_error(
                [
                    'message' => 'Form "' . esc_html($form_id) . '" not found',
                    'code' => 404
                ],
                404,
            );
        }

        $settings_data = Settings::instance()->get_data();
        $field_options = Estatebud::instance()
            ->cache(Cache::TTL_1MO)
            ->get_fields(['component' => 'property']);
        
        ob_start();

        Helper::render_markup_from_views('Public/Form/form-modal.php', [
            'form_id' => $form_id,
            'settings_data' => $settings_data,
            'form_data' => $form_data,
            'field_options' => $field_options,
        ]);

        $rendered_html = ob_get_clean();

        wp_send_json_success(
            [
                'message' => 'Fetched share agent modal',
                'code' => 200,
                'data' => $rendered_html,
            ],
            200,
        );
    }
}
