<?php

if (!class_exists('TaxoPress_Pro_Terms')) {
    /**
     * class TaxoPress_Pro_Terms
     */
    class TaxoPress_Pro_Terms 
    {
        // class instance
        public static $instance;

        /**
         * Construct the TaxoPress_Pro_Terms class
         */
        public function __construct()
        {
            add_action('admin_init', [$this, 'taxopress_pro_copy_terms']);
            add_filter('taxopress_terms_row_actions', [$this, 'taxopress_pro_copy_action'], 10, 2);
            add_action('wp_ajax_taxopress_save_term_order', [$this, 'taxopress_save_term_order_callback']);
        }

        /** Singleton instance */
        public static function get_instance()
        {
            if (!isset(self::$instance)) {
                self::$instance = new self();
            }

            return self::$instance;
        }

        public function taxopress_pro_copy_terms()
        {
            if (isset($_GET['copied_term']) && (int)$_GET['copied_term'] === 1) {
                add_action('admin_notices', [$this, 'taxopress_term_copy_success_admin_notice']);
                add_filter('removable_query_args', [$this, 'taxopress_copied_term_filter_removable_query_args']);
            }

            if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'taxopress-copy-term-with-meta') {
                if (!current_user_can('simple_tags')) {
                    wp_die(esc_html__('Permission denied.', 'taxopress-pro'), '', ['response' => 403]);
                }

                if (isset($_REQUEST['_wpnonce']) && isset($_REQUEST['taxopress_terms'])) {
                    $nonce = sanitize_text_field(wp_unslash($_REQUEST['_wpnonce']));
                    if (wp_verify_nonce($nonce, 'terms-action-request-nonce')) {
                        $this->taxopress_action_copy_term_with_meta(sanitize_text_field(wp_unslash($_REQUEST['taxopress_terms'])));
                    }
                }
                add_filter('removable_query_args', [$this, 'taxopress_copy_term_filter_removable_query_args']);
            }
        }

        public function taxopress_action_copy_term_with_meta($term_id)
        {
            $term = get_term($term_id);
            // Get taxonomy if term is not an object
            if (!is_object($term)) {
                $term_taxonomy = wp_get_object_terms($term_id, get_taxonomies());
                if (!empty($term_taxonomy) && !is_wp_error($term_taxonomy)) {
                    $term = $term_taxonomy[0];
                }
            }

            if ($term && !is_wp_error($term)) {
                if (
                    !taxopress_current_user_can_for_taxonomy(
                        $term->taxonomy,
                        ['edit_terms', 'assign_terms']
                    )
                ) {
                    wp_die(esc_html__('Permission denied.', 'taxopress-pro'), '', ['response' => 403]);
                }

                $new_name = $term->name . ' Copy';
                $base_slug = $term->slug . '-copy';
                $new_slug = taxopress_get_unique_term_slug($base_slug, $term->taxonomy);

                $new_term_data = wp_insert_term($new_name, $term->taxonomy, [
                    'slug' => $new_slug,
                    'description' => $term->description,
                    'parent' => $term->parent,
                ]);

                if (!is_wp_error($new_term_data)) {
                    $new_term = get_term($new_term_data['term_id'], $term->taxonomy);
                    if ($new_term && !is_wp_error($new_term)) {
                        $meta = get_term_meta($term->term_id);
                        foreach ($meta as $key => $values) {
                            foreach ($values as $value) {
                                add_term_meta($new_term->term_id, $key, maybe_unserialize($value));
                            }
                        }

                        // add support for yoast SEO (most seo data already covered by term meta)
                        $yoast_meta = get_option('wpseo_taxonomy_meta');
                        if (!empty($yoast_meta[$term->taxonomy][$term->term_id])) {
                            $original_yoast_data = $yoast_meta[$term->taxonomy][$term->term_id];

                            $yoast_meta[$term->taxonomy][$new_term->term_id] = $original_yoast_data;

                            update_option('wpseo_taxonomy_meta', $yoast_meta);
                        }

                        $args = [
                            'post_type' => 'any',
                            
                            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
                            'tax_query' => [[
                                'taxonomy' => $term->taxonomy,
                                'field' => 'id',
                                'terms' => $term->term_id,
                            ]],
                        ];
                        foreach (taxopress_get_post_ids_for_terms_action($args) as $post_id) {
                            if (!current_user_can('edit_post', $post_id)) {
                                continue;
                            }
                            wp_set_object_terms($post_id, $new_term->term_id, $term->taxonomy, true);
                        }
                        taxopress_place_copied_term_near_original($term->taxonomy, $term->term_id, $new_term->term_id);
                        clean_term_cache($new_term->term_id, $term->taxonomy);
                        delete_transient('taxopress_terms_' . $term->taxonomy);
                    }
                }
            }

            wp_safe_redirect(
                add_query_arg(
                    taxopress_get_terms_screen_query_args([
                        'copied_term'                => 1,
                        'taxopress_copied_term_id'   => isset($new_term->term_id) && !is_wp_error($new_term) ? (int) $new_term->term_id : 0,
                        'taxopress_original_term_id' => isset($term->term_id) && !is_wp_error($term) ? (int) $term->term_id : 0,
                        'taxopress_copied_taxonomy'  => isset($term->taxonomy) && !is_wp_error($term) ? $term->taxonomy : '',
                    ]),
                    admin_url('admin.php')
                )
            );
            exit();
        }

        public function taxopress_term_copy_success_admin_notice()
        {
            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
            echo taxopress_admin_notices_helper(esc_html__('Term successfully copied with metadata.', 'taxopress-pro'), true);
        }

        public function taxopress_copied_term_filter_removable_query_args(array $args)
        {
            return array_merge($args, ['copied_term', 'taxopress_copied_term_id', 'taxopress_original_term_id', 'taxopress_copied_taxonomy']);
        }

        public function taxopress_copy_term_filter_removable_query_args(array $args)
        {
            return array_merge($args, ['action', 'taxopress_terms', '_wpnonce']);
        }

        public function taxopress_pro_copy_action($actions, $item)
        {
            $actions['copy_term_with_meta'] = sprintf(
                '<a href="%s">%s</a>',
                add_query_arg(taxopress_get_terms_screen_query_args([
                    'action'          => 'taxopress-copy-term-with-meta',
                    'taxopress_terms' => esc_attr($item->term_id),
                    '_wpnonce'        => wp_create_nonce('terms-action-request-nonce'),
                ]), admin_url('admin.php')),
                esc_html__('Copy with Metadata', 'taxopress-pro')
            );

            if (isset($actions['copy'])) {
                $new_actions = [];
                foreach ($actions as $key => $action) {
                    if ($key === 'copy') {
                        $new_actions['copy_term_with_meta'] = $actions['copy_term_with_meta'];
                    }
                    $new_actions[$key] = $action;
                }
                return $new_actions;
            }

            return $actions;
        }

        public function taxopress_save_term_order_callback()
        {
    
            if (!current_user_can('simple_tags')) {
                wp_send_json_error(['message' => esc_html__('Permission denied.', 'simple-tags')]);
            }

            if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_key(wp_unslash($_POST['nonce'])), 'st-admin-js')) {
                wp_send_json_error(['message' => esc_html__('Invalid nonce.', 'simple-tags')]);
            }

            $taxonomy = isset($_POST['taxonomy']) ? sanitize_text_field(wp_unslash($_POST['taxonomy'])) : '';
            $order    = isset($_POST['order']) && is_array($_POST['order']) ? array_map('intval', $_POST['order']) : [];

            // Only allow saving if taxonomy is set and not empty
            if (empty($taxonomy) || empty($order)) {
                wp_send_json_error(['message' => esc_html__('Invalid taxonomy or order.', 'simple-tags')]);
            }

            if (!taxonomy_exists($taxonomy)) {
                wp_send_json_error(['message' => esc_html__('Invalid taxonomy.', 'simple-tags')]);
            }

            // Get the current order setting for this taxonomy
            $taxonomy_settings = taxopress_get_all_edited_taxonomy_data();
            $order_setting = isset($taxonomy_settings[$taxonomy]['order']) ? $taxonomy_settings[$taxonomy]['order'] : 'desc';

            // If order is desc, reverse the array before saving
            if ($order_setting === 'desc') {
                $order = array_reverse($order);
            }

            $order = array_values(array_unique(array_filter(array_map('intval', $order))));
            $option_name = 'taxopress_term_order_' . $taxonomy;
            $saved_order = array_values(array_unique(array_filter(array_map('intval', (array) get_option($option_name, [])))));
            $visible_lookup = array_flip($order);

            if (empty($saved_order)) {
                $saved_order = get_terms([
                    'taxonomy'               => [$taxonomy],
                    'hide_empty'             => false,
                    'fields'                 => 'ids',
                    'pad_counts'             => false,
                    'hierarchical'           => false,
                    'update_term_meta_cache' => false,
                ]);

                if (is_wp_error($saved_order)) {
                    $saved_order = [];
                }

                $saved_order = array_values(array_unique(array_filter(array_map('intval', (array) $saved_order))));
            } else {
                $term_count = wp_count_terms([
                    'taxonomy'   => $taxonomy,
                    'hide_empty' => false,
                ]);

                if (!is_wp_error($term_count) && count($saved_order) < (int) $term_count) {
                    $all_term_ids = get_terms([
                        'taxonomy'               => [$taxonomy],
                        'hide_empty'             => false,
                        'fields'                 => 'ids',
                        'pad_counts'             => false,
                        'hierarchical'           => false,
                        'update_term_meta_cache' => false,
                    ]);
                    $missing_term_ids = is_wp_error($all_term_ids)
                        ? []
                        : array_values(array_diff(array_map('intval', (array) $all_term_ids), $saved_order));

                    if (!empty($missing_term_ids)) {
                        $saved_order = array_merge($saved_order, array_map('intval', (array) $missing_term_ids));
                    }
                }
            }

            $visible_positions = [];
            foreach ($saved_order as $position => $term_id) {
                if (isset($visible_lookup[$term_id])) {
                    $visible_positions[] = $position;
                }
            }

            foreach ($visible_positions as $index => $position) {
                if (isset($order[$index])) {
                    $saved_order[$position] = $order[$index];
                }
            }

            $saved_order = array_values(array_unique(array_filter(array_map('intval', $saved_order))));

            update_option($option_name, $saved_order);

            wp_send_json_success(['message' => esc_html__('Order saved.', 'simple-tags')]);
        }
    }
}
