<?php
/**
 * Demo Data Importer for Changeloger
 *
 * Handles importing sample data via AJAX/REST.
 *
 * @package Changeloger
 * @since   2.3.0
 */

defined( 'ABSPATH' ) || exit;

class Changeloger_Demo_Importer {

    /**
     * Import demo data.
     *
     * @return array|WP_Error
     */
    public static function import_demo_data() {
        // Verify permissions.
        if ( ! current_user_can( 'manage_options' ) ) {
            return new WP_Error( 'permission_denied', __( 'You do not have permission to import data.', 'changeloger' ), array( 'status' => 403 ) );
        }

        // Determine which sample file to use based on premium status.
        $is_premium = function_exists('cha_fs') && cha_fs()->can_use_premium_code__premium_only() && class_exists('Changeloger_Pro');

        if ( $is_premium && defined( 'CHANGELOGER_PRO_PATH' ) ) {
            // Use Pro sample data with feedback and roadmap.
            $xml_file = CHANGELOGER_PRO_PATH . 'sample/sample-data.xml';
        } else {
            // Use Free sample data with releases only.
            $xml_file = CHANGELOGER_PATH . 'sample/sample-data.xml';
        }

        // Check if file exists.
        if ( ! file_exists( $xml_file ) ) {
            return new WP_Error( 'file_not_found', __( 'Demo data file not found.', 'changeloger' ), array( 'status' => 404 ) );
        }

        // Load WordPress Importer if needed.
        if ( ! class_exists( 'WP_Import' ) ) {
            $importer_file = ABSPATH . 'wp-admin/includes/class-wp-importer.php';
            if ( file_exists( $importer_file ) ) {
                require_once $importer_file;
            }

            // Try loading the WordPress Importer plugin.
            $plugin_importer = WP_PLUGIN_DIR . '/wordpress-importer/wordpress-importer.php';
            if ( file_exists( $plugin_importer ) ) {
                require_once $plugin_importer;
            }
        }

        // Methods to run recalculations after import
        $recalculate = function() {
            // Flush rewrite rules in case products added new slugs
            flush_rewrite_rules();
            
            // Recalculate term counts if needed, but WP usually handles this on import
            // Triggering a recount for our taxonomies just in case
            $taxonomies = [ 'cha_product', 'cha_feedback_category' ];
            foreach ( $taxonomies as $tax ) {
                $terms = get_terms( [ 'taxonomy' => $tax, 'hide_empty' => false, 'fields' => 'ids' ] );
                if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
                    wp_update_term_count_now( $terms, $tax );
                }
            }
        };

        // If WP_Import still not available, use custom parser.
        if ( ! class_exists( 'WP_Import' ) ) {
            $result = self::custom_import_demo_data( $xml_file );
            if ( is_wp_error( $result ) ) {
                return $result;
            }
            
            $recalculate();

            return [ 'message' => $result ];
        }

        // Use WP_Import if available.
        // We need to suppress output because WP_Import echoes HTML.
        try {
            $importer                    = new WP_Import();
            $importer->fetch_attachments = false;

            ob_start();
            $importer->import( $xml_file );
            ob_end_clean(); // Discard output

            $recalculate();

            return [
                'message' => __( 'Demo data imported successfully!', 'changeloger' ),
            ];
        } catch ( Exception $e ) {
            ob_end_clean(); // Ensure buffer is cleared
            return new WP_Error( 'import_failed', $e->getMessage(), array( 'status' => 500 ) );
        }
    }

    /**
     * Custom XML parser for importing demo data when WP_Import is not available.
     *
     * @param string $xml_file Path to XML file.
     * @return string|WP_Error Success message or error.
     */
    public static function custom_import_demo_data( $xml_file ) {
        // Load XML.
        libxml_use_internal_errors( true );
        $xml = simplexml_load_file( $xml_file );

        if ( false === $xml ) {
            $errors = libxml_get_errors();
            libxml_clear_errors();
            return new WP_Error( 'xml_parse_error', __( 'Failed to parse XML file.', 'changeloger' ) );
        }

        // Register namespaces.
        $namespaces = $xml->getNamespaces( true );
        $wp_ns      = isset( $namespaces['wp'] ) ? $namespaces['wp'] : 'http://wordpress.org/export/1.2/';
        $dc_ns      = isset( $namespaces['dc'] ) ? $namespaces['dc'] : 'http://purl.org/dc/elements/1.1/';
        $content_ns = isset( $namespaces['content'] ) ? $namespaces['content'] : 'http://purl.org/rss/1.0/modules/content/';

        $imported = array(
            'products' => 0,
            'releases' => 0,
            'feedback' => 0,
        );

        $post_id_map     = array();
        $author_map      = array();
        $current_user_id = get_current_user_id();

        // 1. Import/Map Authors
        if ( isset( $xml->channel->children( $wp_ns )->author ) ) {
            foreach ( $xml->channel->children( $wp_ns )->author as $author ) {
                $login        = (string) $author->author_login;
                $email        = (string) $author->author_email;
                $display_name = (string) $author->author_display_name;

                $user = get_user_by( 'login', $login );
                if ( ! $user ) {
                    $user = get_user_by( 'email', $email );
                }

                if ( ! $user ) {
                    // Create new user (subscriber)
                    $user_id = wp_create_user( $login, wp_generate_password(), $email );
                    if ( ! is_wp_error( $user_id ) ) {
                        wp_update_user( array(
                            'ID'           => $user_id,
                            'display_name' => $display_name,
                            'role'         => 'subscriber',
                        ) );
                        $author_map[ $login ] = $user_id;
                    } else {
                        $author_map[ $login ] = $current_user_id;
                    }
                } else {
                    $author_map[ $login ] = $user->ID;
                }
            }
        }

        // 2. Import Terms (Products & Feedback Categories)
        if ( isset( $xml->channel->children( $wp_ns )->term ) ) {
             foreach ( $xml->channel->children( $wp_ns )->term as $term_node ) {
                $taxonomy   = (string) $term_node->term_taxonomy;
                $slug       = (string) $term_node->term_slug;
                $name       = (string) $term_node->term_name;
                
                if ( ! in_array( $taxonomy, [ 'cha_product', 'cha_feedback_category' ] ) ) {
                    continue;
                }

                if ( ! term_exists( $slug, $taxonomy ) ) {
                    wp_insert_term( $name, $taxonomy, [ 'slug' => $slug ] );
                    if ( 'cha_product' === $taxonomy ) {
                        $imported['products']++;
                    }
                }
             }
        }

        // 3. Import Items (Releases, Feedback)
        foreach ( $xml->channel->item as $item ) {
            $wp        = $item->children( $wp_ns );
            $dc        = $item->children( $dc_ns );
            $content   = $item->children( $content_ns );

            $post_type = (string) $wp->post_type;
            
            // Filter post types we care about
            if ( ! in_array( $post_type, [ 'cha_release', 'cha_feedback', 'cha_roadmap_item' ] ) ) {
                 continue;
            }

            $title       = (string) $item->title;
            $post_name   = (string) $wp->post_name;
            $post_content= (string) $content->encoded;
            $post_status = (string) $wp->status;
            $post_date   = (string) $wp->post_date;
            $creator     = (string) $dc->creator;
            $old_id      = (int) $wp->post_id;

            // Determine author
            $post_author = $current_user_id;
            if ( ! empty( $creator ) && isset( $author_map[ $creator ] ) ) {
                $post_author = $author_map[ $creator ];
            }

            // Check existence
            $existing = get_page_by_path( $post_name, OBJECT, $post_type );
            if ( $existing ) {
                $post_id_map[ $old_id ] = $existing->ID;
                continue; // Skip if exists
            }

            // Insert Post
            $post_data = array(
                'post_title'   => $title,
                'post_name'    => $post_name,
                'post_content' => $post_content,
                'post_status'  => $post_status,
                'post_type'    => $post_type,
                'post_author'  => $post_author,
                'post_date'    => $post_date,
            );

            $new_post_id = wp_insert_post( $post_data, true );

            if ( ! is_wp_error( $new_post_id ) ) {
                $post_id_map[ $old_id ] = $new_post_id;
                
                if ( $post_type === 'cha_release' ) $imported['releases']++;
                if ( $post_type === 'cha_feedback' ) $imported['feedback']++;

                // Import Meta
                foreach ( $wp->postmeta as $meta ) {
                    $key = (string) $meta->meta_key;
                    $val = (string) $meta->meta_value;
                    // Maybe handle serialized data (like change items) - WP automatically handles basic values, 
                    // but simplexml returns strings. If it's serialized in XML, it's CDATA string.
                    // update_post_meta handles it if we pass it as string, however,
                    // if it was serialized, we might need to unserialize it first if we want true array storage,
                    // OR if update_post_meta expects raw value. 
                    // Usually WXR has serialized strings. 
                    if ( is_serialized( $val ) ) {
                         $val = unserialize( $val );
                    }
                    update_post_meta( $new_post_id, $key, $val );
                }

                // Import Terms (Categories associated with item)
                if ( isset( $item->category ) ) {
                    foreach ( $item->category as $cat ) {
                        $domain   = (string) $cat['domain'];
                        $nicename = (string) $cat['nicename'];
                        if ( in_array( $domain, [ 'cha_product', 'cha_feedback_category' ] ) ) {
                            // term should exist from step 2
                            wp_set_object_terms( $new_post_id, $nicename, $domain, true );
                        }
                    }
                }
            }
        }

        return sprintf(
            __( 'Successfully imported %1$d products (terms), %2$d releases, and %3$d feedback items.', 'changeloger' ),
            $imported['products'],
            $imported['releases'],
            $imported['feedback']
        );
    }
}
