<?php
namespace Linguator\Custom_Fields;

use Linguator\Settings\Header\Header;

if(!defined('ABSPATH')) exit;

if(!class_exists('Custom_Fields')) {

    class Custom_Fields {
        private static $instance = null;
        private $linguator_saved_fields = array();
        private $linguator_allowed_fields = array();
    
        public static function get_instance() {
            if(null === self::$instance) {
                self::$instance = new self();
            }
            return self::$instance;
        }

        public function __construct() {
            add_action('wp_ajax_lmat_update_custom_fields_content', array($this, 'linguator_update_custom_fields_content'));
            add_filter('lmat_frontend_settings_assets', array($this, 'stop_frontend_setting_assets'), 10, 3);
			add_filter('lmat_admin_settings_assets', array($this, 'linguator_custom_fields_assets'), 10, 3);
			add_filter('lmat_render_languages_page', array($this, 'linguator_render_custom_fields_page'), 10, 3);
        }

		/*
		Filter to enqueue the admin custom fields assets
		@param bool $status
		@param string $tab
		@param bool $is_settings_tab
		@return bool
		*/
        public function linguator_custom_fields_assets($status, $tab, $is_settings_tab){
			if($is_settings_tab && $tab === 'custom-fields' && function_exists('LMAT')){

				$header = Header::get_instance('custom-fields', LMAT()->model);
				$header->header_assets();

                wp_enqueue_script( 'lmat-datatable-script', plugins_url( 'admin/assets/js/dataTables.min.js', LINGUATOR_ROOT_FILE ), array(), LINGUATOR_VERSION, true );
                wp_enqueue_style( 'lmat-editor-custom-fields', plugins_url( 'admin/assets/css/lmat-custom-data-table.min.css', LINGUATOR_ROOT_FILE ), array(), LINGUATOR_VERSION );
                wp_enqueue_script( 'lmat-editor-custom-fields', plugins_url( 'admin/assets/js/lmat-custom-data-table.js', LINGUATOR_ROOT_FILE ), array('lmat-datatable-script'), LINGUATOR_VERSION, true );
            
                wp_localize_script( 'lmat-editor-custom-fields', 'lmatCustomTableDataObject', array(
                    'admin_url' => esc_url(admin_url('admin-ajax.php')),
                    'save_button_handler' => 'lmat_update_custom_fields_content',
                    'save_button_nonce' => wp_create_nonce('lmat_save_custom_fields'),
                    'save_button_enabled'=>true,
                    'save_button_text'=>__('Save Fields', 'translate-words'),
                    'save_button_class'=>'lmat-save-custom-fields',
                ) );
				
				return false;
			}

			return $status;
		}

		/*
		 Filter to stop the admin assets on frontend settings page
		 @param bool $status
		 @param string $tab
		 @param bool $is_settings_tab
		 @return bool
		*/
		public function stop_frontend_setting_assets($status, $tab, $is_settings_tab){
			if($is_settings_tab && $tab === 'custom-fields'){
				return false;
			}

			return $status;
		}
    
		public function linguator_render_custom_fields_page($status, $selected_tab, $active_tab) {
			if($selected_tab === 'custom-fields' && $active_tab === 'settings'){

				$header = Header::get_instance('custom-fields', LMAT()->model);

				$header->header();

				$this->render_custom_fields_page();
				return false;
			}

			return $status;
		}

        public function render_custom_fields_page() {
                $this->linguator_allowed_fields = self::get_allowed_custom_fields();
                $s_no                        = 1;
                ?>
                <div class="lmat-custom-data-table-wrapper lmat-custom-fields">
                    <h3><?php echo esc_html__('Custom Fields Translation Settings', 'translate-words'); ?>
                    <br>
                    <p><?php 
						// translators: %s: Linguator.
						printf( esc_html__( 'Select which custom fields will be translated by %s.', 'translate-words' ), 'Linguator' ); 
					?></p>
                    </h3>
                    <button class="button button-primary lmat-save-custom-fields"><?php esc_html_e( 'Save Fields', 'translate-words' ); ?></button>
                    <div class="lmat-custom-data-table-filters">
                        <div class="lmat-filter-tab" data-column="3" data-default="all">
                            <label for="lmat-fields-filter"><?php esc_html_e( 'Show Fields:', 'translate-words' ); ?></label>
                            <select id="lmat-fields-filter" name="lmat_fields_filter">
                                <option value="all"><?php esc_html_e( 'All', 'translate-words' ); ?></option>
                                <option value="supported"><?php esc_html_e( 'Translatable', 'translate-words' ); ?></option>
                                <option value="unsupported"><?php esc_html_e( 'Non-Translatable', 'translate-words' ); ?></option>
                            </select>
                        </div>
                        <div class="lmat-filter-tab" data-column="2" data-default="all">
                            <label for="lmat-fields-filter"><?php esc_html_e( 'Type:', 'translate-words' ); ?></label>
                            <select id="lmat-fields-value-type-filter" name="lmat_fields_value_type_filter">
                                <option value="all"><?php esc_html_e( 'All', 'translate-words' ); ?></option>
                                <option value="string"><?php esc_html_e( 'String', 'translate-words' ); ?></option>
                                <option value="array"><?php esc_html_e( 'Array', 'translate-words' ); ?></option>
                            </select>
                        </div>
                    </div>
                    <div class="lmat-custom-table-section">
                        <div class="lmat-custom-table-lists">
                            <table class="lmat-custom-data-table-table" id="lmat-custom-datatable">
                                <thead>
                                    <tr>
                                        <th><?php esc_html_e( 'Sr.No', 'translate-words' ); ?></th>
                                        <th><?php esc_html_e( 'Field Name', 'translate-words' ); ?></th>
                                        <th><?php esc_html_e( 'Type', 'translate-words' ); ?></th>
                                        <th><?php esc_html_e( 'Status', 'translate-words' ); ?></th>
                                        <th align="center"><?php esc_html_e( 'Translate', 'translate-words' ); ?></th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <?php
                                        $this->get_all_meta_fields_table();
                                    ?>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
                <?php
        }

        public function get_all_meta_fields_table() {
            $meta_fields=self::linguator_get_custom_fields_data();
            if($meta_fields && is_array($meta_fields)) {
                $s_no                        = 1;
                foreach($meta_fields as $meta_field => $value) { 
                    $checked=isset($this->linguator_allowed_fields[$meta_field]) && !empty($this->linguator_allowed_fields[$meta_field]['status']) ? 'checked' : '';
                    $status=isset($value['status']) && !empty($value['status']) ? $value['status'] : 'Unsupported';
                    $value_type=isset($value['type']) && !empty($value['type']) ? $value['type'] : 'string';
                    
                    echo '<tr>';
                    echo '<td>' . esc_html($s_no++) . '</td>';
                    echo '<td>' . esc_html($meta_field) . '</td>';
                    echo '<td>' . esc_html($value_type) . '</td>';
                    echo '<td>' . esc_html($status) . '</td>';
                    echo '<td align="center"><input type="checkbox" name="lmat_fields_status" value="' . esc_attr($meta_field) . '" ' . esc_attr($checked) . '></td>';
                    echo '</tr>';
                }
            }
        }

        public function linguator_update_custom_fields_content(){
            if ( ! check_ajax_referer( 'lmat_save_custom_fields', 'lmat_nonce', false ) ) {
                wp_send_json_error( __( 'Invalid security token sent.', 'translate-words' ) );
                wp_die( '0', 400 );
            }

            // Plugin-level configuration should be admin-only (not editor-level).
            if ( ! current_user_can( 'manage_options' ) ) {
                wp_send_json_error( __( 'Unauthorized', 'translate-words' ), 403 );
                wp_die( '0', 403 );
            }
            
			// Decode first to avoid corrupting valid JSON payloads.
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw JSON payload; validated via json_decode() + type checks below.
			$raw_json = isset( $_POST['save_custom_fields_data'] ) ? wp_unslash( $_POST['save_custom_fields_data'] ) : '';
			$raw_json = is_string( $raw_json ) ? $raw_json : '';
            $updated_custom_fields_data = json_decode( $raw_json, true );
			if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $updated_custom_fields_data ) ) {
                wp_send_json_error( __( 'Invalid JSON', 'translate-words' ) );
                wp_die( '0', 400 );
            }

			$existing_fields=get_option('lmat_allowed_custom_fields', false);
			$updated_custom_fields_data = array_map( 'sanitize_text_field', $updated_custom_fields_data );

			// json_last_error() already handled above.
			
			$allowed_fields=self::linguator_get_custom_fields_data();

			if(!$allowed_fields || !is_array($allowed_fields)){
				wp_send_json_error( __( 'Invalid allowed fields', 'translate-words' ) );
				wp_die( '0', 400 );
			}

			$allowed_fields_values=array_keys($allowed_fields);

			$valid_fields=array_intersect($updated_custom_fields_data, $allowed_fields_values);
			
			$sanitize_fields=array();
			$old_fields=array();

			foreach($valid_fields as $field){
				if(!isset($existing_fields[$field]) || $existing_fields[$field]['status'] !== true || $existing_fields[$field]['type'] !== $allowed_fields[$field]['type']){
					$sanitize_fields[sanitize_text_field($field)]=['status'=>true, 'type'=>sanitize_text_field($allowed_fields[$field]['type'])];
				}else{
					$old_fields[$field]=$existing_fields[$field];
				}
			}

			$unset_fields=array_diff(array_keys($existing_fields), $updated_custom_fields_data );

			foreach($unset_fields as $field){
				if(isset($existing_fields[$field]) && $existing_fields[$field]['status'] === true){
					$sanitize_fields[$field]=$existing_fields[$field];
					$sanitize_fields[$field]['status']=false;
				}
			}

			if(count($sanitize_fields) < 1){
				wp_send_json_success(array( 'message' => __( 'No changes detected. All selected custom fields are already up to date.', 'translate-words' ) ));
				exit;
			}

			update_option('lmat_allowed_custom_fields', array_merge($old_fields, $sanitize_fields));

			$save_settings=get_option('lmat_allowed_custom_fields', false);

			if ( ! $save_settings || ! is_array( $save_settings ) || count( $save_settings ) < 1 ) {
				wp_send_json_success( array( 'message' => __( 'No custom fields selected. Autopoly cannot translate any fields.', 'translate-words' ) ) );
				exit;
			}

            wp_send_json_success( array(
                'message' => __( 'Custom fields translation settings have been updated successfully. Your selected fields will now be translated automatically.', 'translate-words' ),
                'updated_fields' => $sanitize_fields
            ) );

			exit;
        }

        public static function linguator_get_custom_fields_data(){
			$result=self::linguator_get_custom_fields_query();

			$data=array();

			if($result && is_array($result)){
				$excluded_fields=self::linguator_get_excluded_custom_fields_keys();
				$allowed_fields=self::get_allowed_custom_fields();

				foreach($result as $result){
					if(in_array($result['meta_key'], $excluded_fields)){
						continue;
					}

					$serialized_value=maybe_unserialize($result['meta_value']);
					$value_type=json_decode($result['meta_value'], true) ? 'array' : (is_array($serialized_value) ? 'array' : 'string');
					
					$type=isset($allowed_fields[$result['meta_key']]) && true === $allowed_fields[$result['meta_key']]['status'] ? $allowed_fields[$result['meta_key']]['type'] : $value_type;
					
					$status=isset($allowed_fields[$result['meta_key']]) && true === $allowed_fields[$result['meta_key']]['status'] ? 'Supported' : 'Unsupported';

					$data[sanitize_text_field($result['meta_key'])]=['type'=>$type, 'status'=>$status];
				}
			}

			$default_allowed_fields=self::linguator_get_default_allowed_fields();

			$default_key_diff=array_diff(array_keys($default_allowed_fields), array_keys($data));

			foreach($default_key_diff as $key){
				$status='Supported';
				$saved_allowed_fields=get_option('lmat_allowed_custom_fields', false);
				$status=isset($saved_allowed_fields[$key]) && true === $saved_allowed_fields[$key]['status'] ? 'Supported' : 'Unsupported';

				$data[$key]=['type'=>$default_allowed_fields[$key]['type'], 'status'=>$status];
			}

			$data=apply_filters('lmat/custom_fields/all_fields', $data);

			return $data;
		}

		private static function linguator_get_custom_fields_query(){
			global $wpdb;

             // Escape LIKE pattern for system meta (_%)
			 $like_pattern = $wpdb->esc_like('_') . '%';

            // Get results
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching -- Direct DB query is required here because WordPress core does not provide an efficient or native way to fetch all objects (posts/terms/etc) that do NOT have a language assigned (i.e., not related to any language term_taxonomy_id) in bulk. This negative relationship cannot be expressed using get_terms()/wp_get_object_terms(), especially when type filtering is needed. Using a raw query here ensures both performance and compatibility.
            $results = $wpdb->get_results(
				$wpdb->prepare(
					"
					SELECT DISTINCT pm.meta_key, pm.meta_value
					FROM {$wpdb->postmeta} pm
					WHERE pm.meta_key NOT LIKE %s
					AND pm.meta_value <> ''                         -- skip empty
					AND pm.meta_value NOT IN ('0','1')              -- skip boolean
					AND pm.meta_value NOT REGEXP '^[0-9]+$'         -- skip integer
					AND pm.meta_value NOT REGEXP '^[0-9]+\\.[0-9]+$' -- skip decimal
					AND pm.meta_value NOT REGEXP '^(https?:\/\/|www\.)[A-Za-z0-9\.\-]+.*$' -- skip URLs
					ORDER BY pm.meta_key ASC
					",
					$like_pattern
				), ARRAY_A);

			return $results;
		}

		private static function linguator_get_excluded_custom_fields_keys(){
			$excluded_fields= array(
                '_edit_last',
                '_edit_lock',
                '_wp_page_template',
                '_wp_attachment_metadata',
                '_icl_translator_note',
                '_alp_processed',
                '_pingme',
                '_encloseme',
                '_icl_lang_duplicate_of',
                'atfpp_parent_post_language',
                'atfp_parent_post_language_slug',
                'atfpp_parent_post_language_slug',
                'lmat_parent_post_language',
                'lmat_parent_post_language_slug',
                'twae_exists',
                'twae_post_migration',
                'twae_style_migration',
                '_thumbnail_id',
            );

            return apply_filters('lmat/custom_fields/excluded_keys', $excluded_fields);
		}

		public static function get_allowed_custom_fields(){
			$allowed_custom_fields=self::linguator_get_allowed_custom_fields_data();
			$allowed_custom_fields=apply_filters('lmat/custom_fields/allowed_fields', $allowed_custom_fields);
		
			return $allowed_custom_fields;
		}

		private static function linguator_get_allowed_custom_fields_data(){			
			$allowed_fields=get_option('lmat_allowed_custom_fields', false);

            if(!$allowed_fields){
                $allowed_fields=array();
            }

			if($allowed_fields && is_array($allowed_fields) && count($allowed_fields) > 0){
				return $allowed_fields;
			}

			if(!$allowed_fields || !is_array($allowed_fields)){
				$default_allowed_fields=self::linguator_get_default_allowed_fields();

				foreach($default_allowed_fields as $key => $value){
					$allowed_fields[$key]=['status'=>true, 'type'=>'string'];
				}

				update_option('lmat_allowed_custom_fields', $allowed_fields);
			}

			ksort($allowed_fields);
			
			return $allowed_fields;
		}

		private static function linguator_get_default_allowed_fields(){
			global $wp_filesystem;

			// Initialize the WordPress filesystem.
			if ( ! function_exists( 'WP_Filesystem' ) ) {
				require_once ABSPATH . 'wp-admin/includes/file.php';
			}

			WP_Filesystem();

			$local_path = trailingslashit( LINGUATOR_DIR ) . 'modules/page-translation/block-translation-rules/default-allow-metafields.json';
			if ( $wp_filesystem && $wp_filesystem->exists( $local_path ) && $wp_filesystem->is_readable( $local_path ) ) {
				$default_allowed_fields = $wp_filesystem->get_contents( $local_path );
			} else {
				return array();
			}

			$decoded = json_decode( (string) $default_allowed_fields, true );
			return is_array( $decoded ) ? $decoded : array();
		}
    }
}