<?php

namespace FluentForm\App\Services\Settings;

use FluentForm\App\Models\Form;
use FluentForm\App\Helpers\Helper;
use FluentForm\App\Models\FormMeta;
use FluentForm\Framework\Support\Arr;
use FluentForm\App\Services\FluentConversational\Classes\Form as FluentConversational;

class SettingsService
{
    public function get($attributes = [])
    {
        $metaKey = sanitize_text_field(Arr::get($attributes, 'meta_key'));

        $formId = (int) Arr::get($attributes, 'form_id');

        $result = FormMeta::where(['meta_key' => $metaKey, 'form_id' => $formId])->get();

        foreach ($result as $item) {
            $value = Helper::isJson($item->value) ? json_decode($item->value, true) : $item->value;

            if ('notifications' == $metaKey) {
                if (!$value) {
                    $value = ['name' => ''];
                }
            }

            if (isset($value['layout']) && !isset($value['layout']['asteriskPlacement'])) {
                $value['layout']['asteriskPlacement'] = 'asterisk-right';
            }

            $item->value = $value;
        }
    
        $result = apply_filters_deprecated(
            'fluentform_get_meta_key_settings_response',
            [
                $result,
                $formId,
                $metaKey
            ],
            FLUENTFORM_FRAMEWORK_UPGRADE,
            'fluentform/get_meta_key_settings_response',
            'Use fluentform/get_meta_key_settings_response instead of fluentform_get_meta_key_settings_response'
        );

        return apply_filters('fluentform/get_meta_key_settings_response', $result, $formId, $metaKey);
    }

    public function general($formId)
    {
        $settings = [
            'generalSettings'            => Form::getFormsDefaultSettings($formId),
            'advancedValidationSettings' => Form::getAdvancedValidationSettings($formId),
        ];

        $settings = apply_filters_deprecated(
            'fluentform_form_settings_ajax',
            [
                $settings,
                $formId
            ],
            FLUENTFORM_FRAMEWORK_UPGRADE,
            'fluentform/form_settings_ajax',
            'Use fluentform/form_settings_ajax instead of fluentform/form_settings_ajax'
        );

        $settings = apply_filters('fluentform/form_settings_ajax', $settings, $formId);

        return $settings;
    }

    public function saveGeneral($attributes = [])
    {
        $formId = (int) Arr::get($attributes, 'form_id');

        $formSettings = json_decode(Arr::get($attributes, 'formSettings'), true);

        $formSettings = $this->sanitizeData($formSettings);

        $advancedValidationSettings = json_decode(Arr::get($attributes, 'advancedValidationSettings'), true);

        $advancedValidationSettings = $this->sanitizeData($advancedValidationSettings);

        Validator::validate(
            'confirmations',
            Arr::get($formSettings, 'confirmation', [])
        );

        FormMeta::persist($formId, 'formSettings', $formSettings);

        FormMeta::persist($formId, 'advancedValidationSettings', $advancedValidationSettings);

        $deleteAfterXDaysStatus = Arr::get($formSettings, 'delete_after_x_days');
        $deleteDaysCount = Arr::get($formSettings, 'auto_delete_days');
        $deleteOnSubmission = Arr::get($formSettings, 'delete_entry_on_submission');

        if ('yes' != $deleteOnSubmission && $deleteDaysCount && 'yes' == $deleteAfterXDaysStatus) {
            // We have to set meta values
            FormMeta::persist($formId, 'auto_delete_days', $deleteDaysCount);
        } else {
            // we have to delete meta values
            FormMeta::remove($formId, 'auto_delete_days');
        }

        $convFormPerStepSave = Arr::get($formSettings, 'conv_form_per_step_save') && Helper::isConversionForm($formId);

        if ($convFormPerStepSave) {
            FormMeta::persist($formId, 'conv_form_per_step_save', true);
        } else {
            FormMeta::remove($formId, 'conv_form_per_step_save');
        }

        $convFormResumeFromLastStep = $convFormPerStepSave && Arr::get($formSettings, 'conv_form_resume_from_last_step');
        if ($convFormResumeFromLastStep) {
            FormMeta::persist($formId, 'conv_form_resume_from_last_step', true);
        } else {
            FormMeta::remove($formId, 'conv_form_resume_from_last_step');
        }
      
    
    
        do_action('fluentform/after_save_form_settings', $formId, $attributes);
    }

    private function sanitizeData($settings)
    {
        if (fluentformCanUnfilteredHTML()) {
            return $settings;
        }

        $sanitizerMap = [
            'redirectTo'                 => 'sanitize_text_field',
            'redirectMessage'            => 'fluentform_sanitize_html',
            'messageToShow'              => 'fluentform_sanitize_html',
            'customPage'                 => 'sanitize_text_field',
            'samePageFormBehavior'       => 'sanitize_text_field',
            'customUrl'                  => 'sanitize_url',
            'enabled'                    => 'rest_sanitize_boolean',
            'numberOfEntries'            => 'intval',
            'period'                     => 'sanitize_text_field',
            'limitReachedMsg'            => 'sanitize_text_field',
            'start'                      => 'sanitize_text_field',
            'end'                        => 'sanitize_text_field',
            'pendingMsg'                 => 'sanitize_text_field',
            'expiredMsg'                 => 'sanitize_text_field',
            'requireLoginMsg'            => 'sanitize_text_field',
            'labelPlacement'             => 'sanitize_text_field',
            'helpMessagePlacement'       => 'sanitize_text_field',
            'errorMessagePlacement'      => 'sanitize_text_field',
            'asteriskPlacement'          => 'sanitize_text_field',
            'delete_entry_on_submission' => 'sanitize_text_field',
            'id'                         => 'intval',
            'showLabel'                  => 'rest_sanitize_boolean',
            'showCount'                  => 'rest_sanitize_boolean',
            'status'                     => 'rest_sanitize_boolean',
            'type'                       => 'sanitize_text_field',
            'field'                      => 'sanitize_text_field',
            'operator'                   => 'sanitize_text_field',
            'value'                      => 'sanitize_text_field',
            'error_message'              => 'sanitize_text_field',
            'validation_type'            => 'sanitize_text_field',
            'name'                       => 'sanitize_text_field',
            'email'                      => 'sanitize_text_field',
            'fromName'                   => 'sanitize_text_field',
            'fromEmail'                  => 'sanitize_text_field',
            'replyTo'                    => 'sanitize_text_field',
            'bcc'                        => 'sanitize_text_field',
            'subject'                    => 'sanitize_text_field',
            'message'                    => 'fluentform_sanitize_html',
            'url'                        => 'sanitize_url',
            'webhook'                    => 'sanitize_url',
            'textTitle'                  => 'sanitize_text_field',
            'conv_form_per_step_save'    => 'rest_sanitize_boolean'
        ];

        return fluentform_backend_sanitizer($settings, $sanitizerMap);
    }

    public function store($attributes = [])
    {
        $formId = (int) Arr::get($attributes, 'form_id');

        $value = Arr::get($attributes, 'value', '');

        $valueArray = $value ? json_decode($value, true) : [];

        $key = sanitize_text_field(Arr::get($attributes, 'meta_key'));

        if ('formSettings' == $key) {
            Validator::validate(
                'confirmations',
                Arr::get(
                    $valueArray,
                    'confirmation',
                    []
                )
            );
        } else {
            Validator::validate($key, $valueArray);
        }

        $valueArray = $this->sanitizeData($valueArray);

        $value = json_encode($valueArray);

        $data = [
            'meta_key' => $key,
            'value'    => $value,
            'form_id'  => $formId,
        ];

        // If the request has an valid id field it's safe to assume
        // that the user wants to update an existing settings.
        // So, we'll proceed to do so by finding it first.
        $id = (int) Arr::get($attributes, 'meta_id');

        $settingsQuery = FormMeta::where('form_id', $formId);

        $settings = null;
        if ($id) {
            $settings = $settingsQuery->find($id);
        }

        if (!empty($settings)) {
            $settingsQuery->where('id', $settings->id)->update($data);
            $insertId = $settings->id;
        } else {
            $insertId = $settingsQuery->insertGetId($data);
        }

        return [
            $insertId,
            $valueArray,
        ];
    }

    public function remove($attributes = [])
    {
        $formId = intval(Arr::get($attributes, 'form_id'));
        $id = intval(Arr::get($attributes, 'meta_id'));

        FormMeta::where('form_id', $formId)->where('id', $id)->delete();
    }

    public function conversationalDesign($formId)
    {
        $conversationalForm = new FluentConversational();

        return [
            'design_settings'     => $conversationalForm->getDesignSettings($formId),
            'meta_settings'       => $conversationalForm->getMetaSettings($formId),
            'form_settings'       => Form::getFormsDefaultSettings($formId),
            'pretty_url'          => $this->getPrettyUrlSettings($formId),
            'has_pro'             => defined('FLUENTFORMPRO'),
            'has_pro_share_page'  => $this->hasProSharePage(),
        ];
    }

    public function storeConversationalDesign($attributes, $formId)
    {
        $metaKey = "ffc_form_settings";
        $formId = intval($formId);

        $attributes = fluentFormSanitizer($attributes);
        $settings = Arr::get($attributes, 'design_settings');
        FormMeta::persist($formId, $metaKey . '_design', $settings);

        $generatedCss = wp_strip_all_tags(Arr::get($attributes, 'generated_css'));
        if ($generatedCss) {
            FormMeta::persist($formId, $metaKey . '_generated_css', $generatedCss);
        }

        $meta = Arr::get($attributes, 'meta_settings', []);
        $metaSanitizationMap = [
            'title'             =>  'sanitize_text_field',
            'description'       =>  [$this, 'secureMetaDescription'],
            'featured_image'    =>  'esc_url_raw',
            'share_key'         =>  'sanitize_text_field',
            'google_font_href'  =>  'esc_url_raw',
            'font_css'          =>  'wp_kses_post',
        ];
        foreach ($metaSanitizationMap as $key => $sanitizer) {
            if (isset($meta[$key])) {
                $meta[$key] = call_user_func($sanitizer, $meta[$key]);
            }
        }
        
        if ($meta) {
            FormMeta::persist($formId, $metaKey . '_meta', $meta);
        }

        $prettyUrl = $this->savePrettyUrlSettings(Arr::get($attributes, 'pretty_url'), $formId);

        $formSettings = Arr::get($attributes, 'form_settings');
        if (is_array($formSettings) && isset($formSettings['restrictions'])) {
            $this->saveFormRestrictions($formId, Arr::get($formSettings, 'restrictions', []));
        }

        $params = [
            'fluent-form' => $formId,
        ];
        if (isset($meta['share_key']) && !empty($meta['share_key'])) {
            $params['form'] = $meta['share_key'];
        }

        $shareUrl = add_query_arg($params, Helper::getFrontendFacingUrl());
        return [
            'message'   => __('Settings successfully updated','fluentform'),
            'share_url' => $shareUrl,
            'pretty_url' => $prettyUrl,
        ];
    }

    public function saveFormRestrictions($formId, $restrictions)
    {
        $formId = intval($formId);

        if (!is_array($restrictions)) {
            return Form::getFormsDefaultSettings($formId);
        }

        $existingFormSettings = Form::getFormsDefaultSettings($formId);
        $existingFormSettings['restrictions'] = $restrictions;
        $existingFormSettings = $this->sanitizeData($existingFormSettings);

        FormMeta::persist($formId, 'formSettings', $existingFormSettings);

        return $existingFormSettings;
    }

    public function getPreset($formId)
    {
        $formId = intval($formId);
        $selectedPreset = Helper::getFormMeta($formId, '_ff_selected_style', 'ffs_default');
        $selectedPreset = $selectedPreset ?: 'ffs_default';

        // Use Pro FormStyler presets if available
        if (class_exists('\FluentFormPro\classes\FormStyler')) {
            $formStyler = new \FluentFormPro\classes\FormStyler();
            $presets = $formStyler->getPresets();
        } else {
            $presets = [
                'ffs_default' => [
                    'label' => __('Default', 'fluentform'),
                    'style' => '[]',
                ],
                'ffs_inherit_theme' => [
                    'label' => __('Inherit Theme Style', 'fluentform'),
                    'style' => '{}',
                ],
            ];
        }

        return [
            'selected_preset'=> $selectedPreset,
            'presets' => $presets,
        ];
    }

    /**
     * @throws \Exception
     */
    public function savePreset($attributes)
    {
        $formId = intval(Arr::get($attributes, 'form_id'));
        $selectedPreset = Arr::get($attributes, 'selected_preset');
        if ($selectedPreset && Helper::setFormMeta($formId, '_ff_selected_style', $selectedPreset)) {
            return [
                'message' => __('Settings save successfully', 'fluentform'),
            ];
        }
        throw new \Exception(esc_html__('Settings save failed', 'fluentform'));
    }
    
    public function secureMetaDescription($description) {
        $clean = preg_replace(
            [
                '/url\s*=/',          // Remove URL assignments
                '/http-equiv\s*=/',   // Remove HTTP equiv
                '/refresh/',          // Remove refresh attempts
            ],
            '',
            $description
        );
        
        $clean = wp_strip_all_tags($clean);
        $clean = sanitize_text_field($clean);
        
        return trim($clean);
    }

    private function hasProSharePage()
    {
        return defined('FLUENTFORMPRO') && class_exists('\FluentFormPro\classes\SharePage\SharePage');
    }

    private function hasProPrettyUrl()
    {
        return defined('FLUENTFORMPRO') && class_exists('\FluentFormPro\classes\SharePage\FormPrettyUrlService');
    }

    private function getPrettyUrlSettings($formId)
    {
        if (!$this->hasProPrettyUrl()) {
            return [
                'available'  => false,
                'slug'       => '',
                'enabled'    => false,
                'pretty_url' => '',
                'base_slug'  => 'form',
            ];
        }

        $service = '\FluentFormPro\classes\SharePage\FormPrettyUrlService';
        $slug = $service::getSlug($formId);
        if (!$slug) {
            $form = Form::find($formId);
            $slug = $form ? $service::generateSlug($form->title, $formId) : '';
        }

        return [
            'available'  => true,
            'slug'       => $slug,
            'enabled'    => $service::isEnabled($formId),
            'pretty_url' => $service::getFormPrettyUrl($formId),
            'base_slug'  => $service::getBaseSlug(),
        ];
    }

    private function savePrettyUrlSettings($prettyUrl, $formId)
    {
        if (!is_array($prettyUrl) || !$this->hasProPrettyUrl()) {
            return $this->getPrettyUrlSettings($formId);
        }

        $service = '\FluentFormPro\classes\SharePage\FormPrettyUrlService';
        $slug = sanitize_text_field(Arr::get($prettyUrl, 'slug', ''));
        $enabled = Arr::isTrue($prettyUrl, 'enabled');
        $savedSlug = $service::saveSlug($formId, $slug, $enabled);

        return [
            'available'  => true,
            'slug'       => $savedSlug,
            'enabled'    => $service::isEnabled($formId),
            'pretty_url' => $service::getFormPrettyUrl($formId),
            'base_slug'  => $service::getBaseSlug(),
        ];
    }
}
