<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

require_once __DIR__ . '/class-generic-text-replacer.php';
/**
 * AI整站构建器主类
 * 
 * 功能流程：
 * 1. 收集并结构化用户信息（异步 Job：puffergo/v1/workflow/jobs，type structure-data）
 * 2. 生成网站架构（异步 Job：type site-architecture）
 * 3. 规划页面区块结构（异步 Job：type page-block-planning）
 * 4. Step4 生成 Tailwind 页面（前端经 workflow job `tailwind-generate` 轮询）
 * 5. 创建页面 (create-pages，仅 Tailwind)
 */

class PufferGo_AI_Site_Builder {
    
    public function __construct() {
        puffergo_log('🔥 PufferGo_AI_Site_Builder: Constructor called');

        // REST API路由需要随时可用（前后端都需要）
        add_action('rest_api_init', array($this, 'register_api'));

        // 模板注册和路由已迁移到 PufferGo_Template_Loader::init()
        // Template Loader 负责 theme_page_templates / template_include 钩子

        // 新建页面时自动设置默认模板
        add_action('wp_insert_post', array($this, 'maybe_set_default_template'), 10, 2);

        // Load fullpage styles with high priority to ensure they load after theme styles
        // This allows our defensive CSS resets to properly override theme styles
        add_action('wp_enqueue_scripts', array($this, 'enqueue_fullpage_template_styles'), 100);

        // 后台专用资源只在后台加载（性能优化）；菜单注册见 class-puffergo-admin-menu.php
        if (is_admin()) {
            add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
        }

        // Step3 约定：1 核心 + 5 长尾 = 6 个关键词；RankMath 免费版默认 5 个，扩容到 6。
        add_filter('rank_math/focus_keyword/maxtags', array($this, 'rank_math_focus_keyword_maxtags'));
    }

    /**
     * 将 RankMath 焦点关键词槽位扩容为 6（1 核心 + 5 长尾）。
     *
     * @return int
     */
    public function rank_math_focus_keyword_maxtags() {
        return 6;
    }

    /**
     * Auto-set default page template for newly created pages.
     */
    public function maybe_set_default_template($post_id, $post) {
        static $processed = array();
        if (isset($processed[$post_id])) {
            return;
        }
        $processed[$post_id] = true;

        if ($post->post_type !== 'page') {
            return;
        }

        $default_template = get_option('puffergo_default_page_template', '');
        if (empty($default_template) || $default_template === 'default') {
            return;
        }

        // Only set if current template is empty or 'default' (i.e. not manually chosen)
        $current = get_post_meta($post_id, '_wp_page_template', true);
        if (empty($current) || $current === 'default') {
            update_post_meta($post_id, '_wp_page_template', $default_template);
        }
    }

    /**
     * Enqueue header/footer fallback CSS when page uses PufferGo full-page template.
     */
    public function enqueue_fullpage_template_styles() {
        if ( is_admin() ) {
            return;
        }

        $is_fullpage_page    = false;
        $is_product          = is_singular( 'puffergo_product' );
        $is_product_archive  = is_post_type_archive( 'puffergo_product' ) || is_tax( 'puffergo_product_cat' );
        $is_blog             = is_singular( 'post' )
                               || is_category()
                               || is_post_type_archive( 'post' )
                               || ( is_home() && ! is_front_page() );

        if ( is_singular( 'page' ) ) {
            $page_id = get_queried_object_id();
            if ( $page_id ) {
                $template = get_post_meta( $page_id, '_wp_page_template', true );
                if ( $template === 'puffergo-fullpage.php' ) {
                    $is_fullpage_page = true;
                }
            }
        }

        if ( ! $is_fullpage_page && ! $is_product && ! $is_product_archive && ! $is_blog ) {
            return;
        }

        $version = defined( 'PUFFERGO_CORE_VERSION' ) ? PUFFERGO_CORE_VERSION : '1.0.0';
        $base    = plugins_url( 'assets/css/', PUFFERGO_PLUGIN_FILE );

        // Compiled Tailwind utilities (scoped to .puffergo-fullpage-layout)
        wp_enqueue_style(
            'puffergo-tailwind',
            $base . 'tailwind.css',
            array( 'puffergo' ),
            $version
        );

        // Token bridge: maps Tailwind fixed colors → CSS variables.
        // Must load AFTER tailwind.css (same specificity, last wins).
        wp_enqueue_style(
            'puffergo-token-bridge',
            $base . 'token-bridge.css',
            array( 'puffergo-tailwind' ),
            $version
        );

        // Body background — only on fullpage/product pages.
        wp_add_inline_style( 'puffergo', 'body { background-color: #fff !important; }' );
    }
    
    /**
     * 注册REST API端点
     */
    public function register_api() {
        puffergo_log('🔥 PufferGo_AI_Site_Builder: register_api() called');
        
        // Profile 默认结构（后端唯一定义，保留以兼容旧版前端）
        register_rest_route('puffergo/v1', '/workflow/profile-default', array(
            'methods' => 'GET',
            'callback' => array($this, 'profile_default'),
            'permission_callback' => array($this, 'check_permission'),
        ));

        // 工作流默认值聚合（方案二：一次返回 profile + step2 + step3）
        register_rest_route('puffergo/v1', '/workflow/defaults', array(
            'methods' => 'GET',
            'callback' => array($this, 'workflow_defaults'),
            'permission_callback' => array($this, 'check_permission'),
        ));

        // Save global elements (header/footer from step2) when user confirms Step 2.
        register_rest_route('puffergo/v1', '/save-global-elements', array(
            'methods' => 'POST',
            'callback' => array($this, 'save_global_elements'),
            'permission_callback' => array($this, 'check_permission'),
        ));

        // Header nav alignment (left/center/right) for fullpage template.
        register_rest_route('puffergo/v1', '/header-nav-align', array(
            'methods' => 'GET',
            'callback' => array($this, 'get_header_nav_align'),
            'permission_callback' => '__return_true',
        ));
        register_rest_route('puffergo/v1', '/header-nav-align', array(
            'methods' => 'POST',
            'callback' => array($this, 'update_header_nav_align'),
            'permission_callback' => array($this, 'check_permission'),
        ));

        // Header template (header / header-2) for fullpage template.
        register_rest_route( 'puffergo/v1', '/header-template', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'get_header_template' ),
            'permission_callback' => '__return_true',
        ));
        register_rest_route( 'puffergo/v1', '/header-template', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'update_header_template' ),
            'permission_callback' => array( $this, 'check_permission' ),
        ));

        // Footer template (footer / footer-2) for fullpage template.
        register_rest_route( 'puffergo/v1', '/footer-template', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'get_footer_template' ),
            'permission_callback' => '__return_true',
        ));
        register_rest_route( 'puffergo/v1', '/footer-template', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'update_footer_template' ),
            'permission_callback' => array( $this, 'check_permission' ),
        ));


        // Step 5: 批量创建页面（Tailwind）
        register_rest_route('puffergo/v1', '/create-pages', array(
            'methods' => 'POST',
            'callback' => array($this, 'create_pages'),
            'permission_callback' => array($this, 'check_permission'),
        ));
        
        // Step 5: 发布页面
        register_rest_route('puffergo/v1', '/publish-pages', array(
            'methods' => 'POST',
            'callback' => array($this, 'publish_pages'),
            'permission_callback' => array($this, 'check_permission'),
        ));
        

        // Step 4.5: 生成页面填充内容（按页面维度）
        register_rest_route('puffergo/v1', '/workflow/generate-page-content', array(
            'methods' => 'POST',
            'callback' => array($this, 'generate_page_content'),
            'permission_callback' => array($this, 'check_permission'),
        ));
    }

    /* =====================================================
     * 🧹 CLEAR PRIMARY MENU (CALLED ONCE AT BATCH START)
     * ===================================================== */
    /**
     * Ensure puffergo_primary menu exists, then clear all items.
     */
    private function clear_puffergo_primary_menu() {
        $menu_id = puffergo_ensure_primary_menu();
        if ( $menu_id <= 0 ) {
            puffergo_log( 'Failed to create puffergo_primary menu' );
            return false;
        }

        $existing_items = wp_get_nav_menu_items( $menu_id );
        if ( ! $existing_items ) {
            return true;
        }

        $deleted_count = 0;
        foreach ( $existing_items as $item ) {
            if ( wp_delete_post( $item->ID, true ) ) {
                $deleted_count++;
            }
        }

        puffergo_log( "Cleared {$deleted_count} items from puffergo_primary menu (ID: {$menu_id})" );
        return true;
    }

    /**
     * Add a WP page to puffergo_primary menu.
     */
    private function add_page_to_puffergo_primary( $page_id, $title ) {
        $menu_id = puffergo_ensure_primary_menu();
        if ( $menu_id <= 0 ) {
            return false;
        }
        return puffergo_add_page_to_menu( $menu_id, $page_id, $title );
    }

    /**
     * Inject structural pages (products, blog) into a menu as links.
     * - link_only: custom link to CPT archive
     * - create_and_link: create empty WP page + set option + add as post_type item
     *
     * @param int   $menu_id          Menu term ID.
     * @param array $structural_pages Array of structural page definitions.
     */
    private function ensure_structural_links_in_menu( $menu_id, $structural_pages ) {
        if ( empty( $structural_pages ) || ! is_array( $structural_pages ) ) {
            return;
        }

        foreach ( $structural_pages as $sp ) {
            $action = isset( $sp['action'] ) ? $sp['action'] : 'link_only';
            $name   = isset( $sp['name'] ) ? $sp['name'] : '';
            $path   = isset( $sp['path'] ) ? $sp['path'] : '';

            if ( $action === 'create_and_link' ) {
                // Create empty WP page
                $slug = ltrim( $path, '/' );
                $page_id = wp_insert_post( array(
                    'post_title'  => $name,
                    'post_name'   => $slug,
                    'post_status' => 'publish',
                    'post_type'   => 'page',
                    'post_content' => '',
                ), true );

                if ( is_wp_error( $page_id ) ) {
                    puffergo_log( "Failed to create structural page '{$name}': " . $page_id->get_error_message() );
                    continue;
                }

                // Blog: set as posts page
                if ( isset( $sp['pageType'] ) && $sp['pageType'] === 'BLOG_LIST_PAGE' ) {
                    update_option( 'page_for_posts', $page_id );
                }

                puffergo_add_page_to_menu( $menu_id, $page_id, $name );
                puffergo_log( "Created structural page '{$name}' (ID: {$page_id}) and added to menu" );

            } else {
                // link_only: custom link
                $url = home_url( $path );
                puffergo_add_custom_link_to_menu( $menu_id, $name, $url );
                puffergo_log( "Added structural link '{$name}' ({$url}) to menu" );
            }
        }
    }
    
    /**
     * 检查权限
     */
    public function check_permission() {
    return current_user_can('edit_posts');
}
    
    /**
     * 渲染后台管理页面（菜单回调，由 PufferGo_Admin_Menu 注册）
     */
    public static function render_admin_page() {
        ?>
        <div class="wrap">
            <div id="puffergo_admin_wrapper" class="puffergo-admin-wrapper"></div>
        </div>
        <?php
    }
    
    /**
     * 加载脚本（在 AI 智能建站页面）
     */
    public function enqueue_scripts($hook) {
        if ($hook !== 'puffergo_page_puffergo-ai-site-builder') {
            return;
        }

        // Step4 AI edit modal: replace image needs the media library.
        wp_enqueue_media();

        $plugin_url = plugin_dir_url(dirname(__FILE__));
        $asset_file = plugin_dir_path(dirname(__FILE__)) . 'build/blocks/ai-site-builder-app/index.asset.php';
        
        if (file_exists($asset_file)) {
            $asset = include $asset_file;
            $dependencies = $asset['dependencies'];
            $version = $asset['version'];
        } else {
            $dependencies = array(
                'wp-element',
                'wp-components',
                'wp-api-fetch',
                'wp-data',
                'wp-hooks'
            );
            $version = time();
        }
        
        wp_enqueue_script(
            'puffergo-ai-site-builder',
            $plugin_url . 'build/blocks/ai-site-builder-app/index.js',
            $dependencies,
            $version,
            true
        );
        
        $css_file = plugin_dir_path(dirname(__FILE__)) . 'build/blocks/ai-site-builder-app/index.css';
        if (file_exists($css_file)) {
            wp_enqueue_style(
                'puffergo-ai-site-builder-styles',
                $plugin_url . 'build/blocks/ai-site-builder-app/index.css',
                array('puffergo-admin-tailwind'),
                $version
            );
        }

        $style_index_css = plugin_dir_path(dirname(__FILE__)) . 'build/blocks/ai-site-builder-app/style-index.css';
        if (file_exists($style_index_css)) {
            wp_enqueue_style(
                'puffergo-ai-site-builder-style',
                $plugin_url . 'build/blocks/ai-site-builder-app/style-index.css',
                array('puffergo-admin-tailwind'),
                $version
            );
        }

        // Theme CSS variables so Step 4 preview matches edit page (same :root vars as block editor).
        $theme_bridge = new PufferGo_Theme_Bridge();
        wp_localize_script('puffergo-ai-site-builder', 'puffergoAiSiteBuilder', array(
            'restUrl' => rest_url('puffergo/v1/'),
            'nonce' => wp_create_nonce('wp_rest'),
            'currentUserId' => get_current_user_id(),
            'adminUrl' => admin_url(),
            'dashboardUrl' => admin_url('admin.php?page=puffergo'),
            'hasApiKey' => ! empty( get_option( 'puffergo_api_key', '' ) ),
            'connectUrl' => PUFFERGO_BASE_URL . '/dashboard/connect',
            'siteName' => get_bloginfo( 'name' ),
            'themeCssVars' => $theme_bridge->get_css_variables(),
            'locale' => get_user_locale(),
        ));

        PufferGo_Workflow_Jobs_REST::add_poll_config_inline_script( 'puffergo-ai-site-builder' );

        wp_enqueue_style('wp-components');
    }
    
    /** 默认 profile 的 transient 缓存 key（未用 defaults 时） */
    const PROFILE_DEFAULT_TRANSIENT = 'puffergo_profile_default';

    /** 工作流默认值聚合缓存 key（profile + step2 + step3 一次拉取） */
    const WORKFLOW_DEFAULTS_TRANSIENT = 'puffergo_workflow_defaults';

    /**
     * 返回默认站点信息结构。优先从后端 GET /workflow/defaults 聚合接口拉取（带缓存），失败则单接口 profile-default，再失败则本地 fallback。
     *
     * @return array
     */
    private function get_default_site_profile() {
        $cached = get_transient( self::WORKFLOW_DEFAULTS_TRANSIENT );
        if ( is_string( $cached ) ) {
            $decoded = json_decode( $cached, true );
            if ( ! empty( $decoded['defaults']['profile'] ) && is_array( $decoded['defaults']['profile'] ) ) {
                return $decoded['defaults']['profile'];
            }
        }
        try {
            $data = $this->call_workflow_api_get( '/api/workflow/defaults' );
            if ( ! empty( $data['defaults']['profile'] ) && is_array( $data['defaults']['profile'] ) ) {
                set_transient( self::WORKFLOW_DEFAULTS_TRANSIENT, wp_json_encode( $data ), HOUR_IN_SECONDS );
                return $data['defaults']['profile'];
            }
        } catch ( Exception $e ) {
            puffergo_log( 'AI Site Builder: get_default_site_profile (defaults) 失败 - ' . $e->getMessage() );
        }
        $cached = get_transient( self::PROFILE_DEFAULT_TRANSIENT );
        if ( is_string( $cached ) ) {
            $decoded = json_decode( $cached, true );
            if ( is_array( $decoded ) ) {
                return $decoded;
            }
        }
        try {
            $data = $this->call_workflow_api_get( '/api/workflow/profile-default' );
            if ( ! empty( $data['defaultProfile'] ) && is_array( $data['defaultProfile'] ) ) {
                set_transient( self::PROFILE_DEFAULT_TRANSIENT, wp_json_encode( $data['defaultProfile'] ), HOUR_IN_SECONDS );
                return $data['defaultProfile'];
            }
        } catch ( Exception $e ) {
            puffergo_log( 'AI Site Builder: get_default_site_profile (profile-default) 失败 - ' . $e->getMessage() );
        }
        return $this->get_fallback_default_site_profile();
    }

    /**
     * 返回缓存的完整工作流默认值（defaults.profile / .step2 / .step3），无缓存则拉取并缓存。
     *
     * @return array|null 成功为 array('defaults' => array('profile'=>...,'step2'=>...,'step3'=>...), 'version'=>...)，失败为 null
     */
    private function get_workflow_defaults() {
        $cached = get_transient( self::WORKFLOW_DEFAULTS_TRANSIENT );
        if ( is_string( $cached ) ) {
            $decoded = json_decode( $cached, true );
            if ( ! empty( $decoded['defaults'] ) && is_array( $decoded['defaults'] ) ) {
                return $decoded;
            }
        }
        try {
            $data = $this->call_workflow_api_get( '/api/workflow/defaults' );
            if ( ! empty( $data['defaults'] ) && is_array( $data['defaults'] ) ) {
                set_transient( self::WORKFLOW_DEFAULTS_TRANSIENT, wp_json_encode( $data ), HOUR_IN_SECONDS );
                return $data;
            }
        } catch ( Exception $e ) {
            puffergo_log( 'AI Site Builder: get_workflow_defaults 失败 - ' . $e->getMessage() );
        }
        return null;
    }

    /**
     * 本地 fallback 默认结构（与后端 defaultProfile 同构，仅在后端不可用时使用）。
     *
     * @return array
     */
    private function get_fallback_default_site_profile() {
        return array(
            'audience'  => array( 'role' => '', 'priorities' => '', 'use_cases' => '', 'regions' => '' ),
            'identity'  => array( 'brand_name' => '', 'slogan' => '', 'founded' => '', 'story' => '' ),
            'contact'   => array( 'email' => '', 'phone' => '', 'address' => '', 'channels' => array() ),
            'business'  => array( 'industry' => '', 'products' => array() ),
            'advantage' => array( 'certs' => '', 'pillars' => array(), 'pain_points' => '', 'tone' => 'Professional' ),
            'assets'    => array(
                'logo_attachment_id' => 0,
                'logo_url'           => '',
            ),
            'seo'       => array( 'keywords' => array() ),
            'special_instructions' => '',
        );
    }

    /**
     * 规范化 profile（补齐缺失键、产品项字段），供 builder 使用。
     *
     * @param array $profile 原始 profile。
     * @return array
     */
    /**
     * 规范化 profile，补齐缺失键；保留后端新增的未知键（兼容未更新插件，见 profile-backward-compatibility.md）。
     */
    private function normalize_profile_for_builder( $profile ) {
        $default = $this->get_default_site_profile();
        $merged = array();
        foreach ( array_keys( $default ) as $block ) {
            // special_instructions 为字符串，不能走 array_merge，否则会用 default('') 覆盖接口返回值
            if ( $block === 'special_instructions' ) {
                $merged[ $block ] = ( isset( $profile[ $block ] ) && is_string( $profile[ $block ] ) )
                    ? sanitize_textarea_field( $profile[ $block ] )
                    : $default[ $block ];
                continue;
            }
            $merged[ $block ] = isset( $profile[ $block ] ) && is_array( $profile[ $block ] )
                ? array_merge( $default[ $block ], $profile[ $block ] )
                : $default[ $block ];
        }
        // 保留后端新增的顶层键，避免旧版插件丢弃新字段
        foreach ( array_keys( $profile ) as $block ) {
            if ( ! array_key_exists( $block, $merged ) ) {
                $merged[ $block ] = $profile[ $block ];
            }
        }
        $prods = isset( $merged['business']['products'] ) && is_array( $merged['business']['products'] ) ? $merged['business']['products'] : array();
        $merged['business']['products'] = array_slice( array_map( function ( $p ) {
            $name = is_array( $p ) && isset( $p['name'] ) ? $p['name'] : ( is_string( $p ) ? $p : '' );
            return array( 'name' => $name );
        }, $prods ), 0, 3 );
        if ( ! isset( $merged['advantage']['pillars'] ) || ! is_array( $merged['advantage']['pillars'] ) ) {
            $merged['advantage']['pillars'] = array();
        }
        // seo.keywords：统一为数组，最多 30 个
        $kw = isset( $merged['seo']['keywords'] ) ? $merged['seo']['keywords'] : array();
        $merged['seo']['keywords'] = is_array( $kw )
            ? array_slice( array_map( 'sanitize_text_field', array_filter( $kw, 'is_string' ) ), 0, 30 )
            : ( is_string( $kw ) ? array_slice( array_filter( array_map( 'trim', preg_split( '/[\n,]+/', $kw ) ) ), 0, 30 ) : array() );
        return $merged;
    }

    /**
     * GET Profile 默认结构（代理到后端，保留以兼容旧版前端）
     */
    public function profile_default( $request ) {
        try {
            $data = $this->call_workflow_api_get( '/api/workflow/profile-default' );
            return new WP_REST_Response( array( 'success' => true, 'data' => $data ), 200 );
        } catch ( Exception $e ) {
            puffergo_log( 'AI Site Builder: profile-default 失败 - ' . $e->getMessage() );
            return new WP_REST_Response( array(
                'success' => false,
                'message' => $e->getMessage(),
            ), 500 );
        }
    }

    /**
     * GET 工作流默认值聚合（方案二：一次返回 profile + step2 + step3）
     */
    public function workflow_defaults( $request ) {
        try {
            $data = $this->call_workflow_api_get( '/api/workflow/defaults' );
            return new WP_REST_Response( array( 'success' => true, 'data' => $data ), 200 );
        } catch ( Exception $e ) {
            puffergo_log( 'AI Site Builder: workflow/defaults 失败 - ' . $e->getMessage() );
            return new WP_REST_Response( array(
                'success' => false,
                'message' => $e->getMessage(),
            ), 500 );
        }
    }

    /**
     * Save global elements (step2 footer/header) when user confirms Step 2.
     * Ensures fullpage template has footer data even before Step 5 runs.
     */
    public function save_global_elements( $request ) {
        $params = $request->get_json_params();
        $global_elements = isset( $params['globalElements'] ) && is_array( $params['globalElements'] ) ? $params['globalElements'] : array();

        if ( ! empty( $global_elements['footer'] ) && is_array( $global_elements['footer'] ) ) {
            $footer_data = $this->sanitize_step2_footer_data( $global_elements['footer'] );
            $this->upsert_footer_menu_from_step2( $footer_data );
            if ( ! empty( $footer_data['copyright'] ) ) {
                update_option( 'puffergo_site_footer_copyright', $footer_data['copyright'] );
            }
        }

        return new WP_REST_Response( array( 'success' => true ), 200 );
    }

    /**
     * Get header nav alignment option (for fullpage template).
     *
     * @return WP_REST_Response
     */
    public function get_header_nav_align() {
        $align = get_option( 'puffergo_header_nav_align', 'right' );
        $allowed = array( 'left', 'center', 'right' );
        if ( ! in_array( $align, $allowed, true ) ) {
            $align = 'right';
        }
        return new WP_REST_Response( array( 'align' => $align ), 200 );
    }

    /**
     * Update header nav alignment option.
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response
     */
    public function update_header_nav_align( $request ) {
        $params = $request->get_json_params();
        $align = isset( $params['align'] ) ? sanitize_key( $params['align'] ) : '';
        $allowed = array( 'left', 'center', 'right' );
        if ( ! in_array( $align, $allowed, true ) ) {
            return new WP_REST_Response( array( 'success' => false, 'message' => __( 'Invalid align value.', 'puffergo' ) ), 400 );
        }
        update_option( 'puffergo_header_nav_align', $align );
        return new WP_REST_Response( array( 'success' => true, 'align' => $align ), 200 );
    }

    /**
     * Get header template option (for fullpage template).
     *
     * @return WP_REST_Response
     */
    public function get_header_template() {
		$template = PufferGo_Template_Loader::get_active_header();
        return new WP_REST_Response( array( 'template' => $template ), 200 );
    }

    /**
     * Update header template option.
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response
     */
    public function update_header_template( $request ) {
        $params   = $request->get_json_params();
        $template = isset( $params['template'] ) ? sanitize_key( $params['template'] ) : '';
        if ( ! PufferGo_Template_Loader::is_valid_header( $template ) ) {
            return new WP_REST_Response( array( 'success' => false, 'message' => __( 'Invalid template value.', 'puffergo' ) ), 400 );
        }
        update_option( 'puffergo_header_template', $template );
        return new WP_REST_Response( array( 'success' => true, 'template' => $template ), 200 );
    }

    /**
     * Get footer template option (for fullpage template).
     *
     * @return WP_REST_Response
     */
    public function get_footer_template() {
        $template = PufferGo_Template_Loader::get_active_footer();
        return new WP_REST_Response( array( 'template' => $template ), 200 );
    }

    /**
     * Update footer template option.
     *
     * @param WP_REST_Request $request Request.
     * @return WP_REST_Response
     */
    public function update_footer_template( $request ) {
        $params   = $request->get_json_params();
        $template = isset( $params['template'] ) ? sanitize_key( $params['template'] ) : '';
        if ( ! PufferGo_Template_Loader::is_valid_footer( $template ) ) {
            return new WP_REST_Response( array( 'success' => false, 'message' => __( 'Invalid template value.', 'puffergo' ) ), 400 );
        }
        update_option( 'puffergo_footer_template', $template );
        return new WP_REST_Response( array( 'success' => true, 'template' => $template ), 200 );
    }

    /**
     * Step 5: 批量创建页面（仅 Tailwind 模式）
     */
    public function create_pages( $request ) {
        puffergo_log( '=== AI Site Builder: Step 5 - 创建页面 ===' );
        $start_time = microtime( true );

        $params = $request->get_json_params();
        $pages_data         = $params['pages'] ?? array();
        $global_elements    = $params['globalElements'] ?? array();
        $structural_pages   = $params['structuralPages'] ?? array();

        if ( empty( $pages_data ) ) {
            return new WP_REST_Response(
                array(
                    'success' => false,
                    'message' => __( 'No page data', 'puffergo' ),
                ),
                400
            );
        }

        // 1. Ensure and clear PufferGo's own primary menu.
        $this->clear_puffergo_primary_menu();

        // 2. Create AI-generated pages.
        $results       = array();
        $success_count = 0;
        $fail_count    = 0;
        $homepage_id   = 0;

        foreach ( $pages_data as $page_data ) {
            try {
                $site_pages = $params['sitePages'] ?? array();
                $page_id    = $this->create_tailwind_page( $page_data, $site_pages );

                // Track homepage (first page or pageType HOME_PAGE).
                if ( $homepage_id === 0 || ( isset( $page_data['pageType'] ) && $page_data['pageType'] === 'HOME_PAGE' ) ) {
                    $homepage_id = $page_id;
                }

                $results[] = array(
                    'success'  => true,
                    'pageId'   => $page_id,
                    'pageName' => $page_data['name'] ?? '',
                    'editUrl'  => admin_url( 'post.php?post=' . $page_id . '&action=edit' ),
                    'viewUrl'  => get_permalink( $page_id ),
                );
                ++$success_count;
                puffergo_log( 'AI Site Builder: 页面创建成功 - ' . ( $page_data['name'] ?? '' ) . ' (ID: ' . $page_id . ')' );

            } catch ( \Throwable $e ) {
                $results[] = array(
                    'success'  => false,
                    'pageName' => $page_data['name'] ?? '',
                    'error'    => $e->getMessage(),
                );
                ++$fail_count;
                puffergo_log( 'AI Site Builder: 页面创建失败 - ' . ( $page_data['name'] ?? '' ) . ': ' . $e->getMessage() );
            }
        }

        // 3. Set homepage as front page.
        if ( $homepage_id > 0 ) {
            update_option( 'page_on_front', $homepage_id );
            update_option( 'show_on_front', 'page' );
            puffergo_log( 'Set page_on_front = ' . $homepage_id );
        }

        // 4. Inject structural pages (products, blog) into primary menu.
        $primary_menu_id = puffergo_ensure_primary_menu();
        if ( $primary_menu_id > 0 && ! empty( $structural_pages ) ) {
            $this->ensure_structural_links_in_menu( $primary_menu_id, $structural_pages );
        }

        // 5. Persist step2 footer data.
        if ( ! empty( $global_elements['footer'] ) && is_array( $global_elements['footer'] ) ) {
            $footer_data = $this->sanitize_step2_footer_data( $global_elements['footer'] );
            $this->upsert_footer_menu_from_step2( $footer_data );
            if ( ! empty( $footer_data['copyright'] ) ) {
                update_option( 'puffergo_site_footer_copyright', $footer_data['copyright'] );
            }
        }

        // 6. Inject structural links into footer menu.
        $footer_menu_id = puffergo_resolve_menu_id( 'puffergo_footer', 'PufferGo Footer' );
        if ( $footer_menu_id > 0 && ! empty( $structural_pages ) ) {
            $this->ensure_structural_links_in_menu( $footer_menu_id, $structural_pages );
        }

        $duration = microtime( true ) - $start_time;
        puffergo_log( 'AI Site Builder: 批量创建完成，成功: ' . $success_count . '，失败: ' . $fail_count . '，耗时: ' . round( $duration, 4 ) . ' 秒' );

        return new WP_REST_Response(
            array(
                'success' => true,
                'data'    => array(
                    'results' => $results,
                    'summary' => array(
                        'mode'    => 'tailwind',
                        'total'   => count( $pages_data ),
                        'success' => $success_count,
                        'failed'  => $fail_count,
                    ),
                ),
            ),
            200
        );
    }

    /**
     * Sanitize step2 footer data (sections + copyright) for storage.
     *
     * @param array $footer Raw footer from step2 globalElements.
     * @return array Sanitized array with 'sections' and 'copyright'.
     */
    private function sanitize_step2_footer_data( array $footer ) {
        $out = array(
            'sections' => array(),
            'copyright' => '',
        );
        if ( ! empty( $footer['copyright'] ) && is_string( $footer['copyright'] ) ) {
            $out['copyright'] = sanitize_text_field( $footer['copyright'] );
        }
        if ( empty( $footer['sections'] ) || ! is_array( $footer['sections'] ) ) {
            return $out;
        }
        foreach ( $footer['sections'] as $section ) {
            $title = isset( $section['title'] ) && is_string( $section['title'] )
                ? sanitize_text_field( $section['title'] )
                : '';
            $links = array();
            if ( ! empty( $section['links'] ) && is_array( $section['links'] ) ) {
                foreach ( $section['links'] as $link ) {
                    $name = isset( $link['name'] ) && is_string( $link['name'] )
                        ? sanitize_text_field( $link['name'] )
                        : '';
                    $url  = isset( $link['url'] ) && is_string( $link['url'] )
                        ? sanitize_text_field( $link['url'] )
                        : '';
                    if ( $name !== '' || $url !== '' ) {
                        $links[] = array( 'name' => $name, 'url' => $url );
                    }
                }
            }
            $out['sections'][] = array( 'title' => $title, 'links' => $links );
        }
        return $out;
    }

    /**
     * Create or update the PufferGo footer menu from sanitized step2 footer data.
     *
     * Mapping:
     * - sections[].title -> top-level menu item (custom URL "#")
     * - sections[].links[] -> child items under that section (custom URL)
     *
     * @param array $footer_data Sanitized array from sanitize_step2_footer_data().
     * @return void
     */
    private function upsert_footer_menu_from_step2( array $footer_data ) {
        $menu_id = puffergo_ensure_footer_menu();
        if ( $menu_id <= 0 ) {
            puffergo_log( 'Footer menu ensure failed', 'AI Site Builder' );
            return;
        }

        // Clear existing menu items.
        $existing_items = wp_get_nav_menu_items( $menu_id );
        if ( is_array( $existing_items ) ) {
            foreach ( $existing_items as $item ) {
                if ( isset( $item->ID ) ) {
                    wp_delete_post( (int) $item->ID, true );
                }
            }
        }

        $sections = isset( $footer_data['sections'] ) && is_array( $footer_data['sections'] ) ? $footer_data['sections'] : array();

        // Rebuild menu items from sections.
        foreach ( $sections as $section ) {
            $title = isset( $section['title'] ) ? (string) $section['title'] : '';
            $links = isset( $section['links'] ) && is_array( $section['links'] ) ? $section['links'] : array();
            if ( $title === '' || empty( $links ) ) {
                continue;
            }

            $parent_item_id = wp_update_nav_menu_item(
                $menu_id,
                0,
                array(
                    'menu-item-title'  => $title,
                    'menu-item-url'    => '#',
                    'menu-item-type'   => 'custom',
                    'menu-item-status' => 'publish',
                )
            );
            if ( is_wp_error( $parent_item_id ) ) {
                puffergo_log( 'Footer menu parent item failed: ' . $parent_item_id->get_error_message(), 'AI Site Builder' );
                continue;
            }

            foreach ( $links as $link ) {
                $name = isset( $link['name'] ) ? (string) $link['name'] : '';
                $url  = isset( $link['url'] ) ? (string) $link['url'] : '';
                if ( $name === '' ) {
                    continue;
                }
                $url = trim( $url );
                if ( $url === '' ) {
                    continue;
                }

                // Write-time normalization: templates should only `esc_url()` and render.
                // - Keep scheme URLs (tel/mailto/http/https/...)
                // - Convert raw email/phone into mailto:/tel:
                // - For remaining relative URLs, prefix home_url()
                if ( $url !== '#' && preg_match( '/^[a-zA-Z][a-zA-Z0-9+\-.]*:/', $url ) !== 1 ) {
                    // Email -> mailto:
                    if ( false !== filter_var( $url, FILTER_VALIDATE_EMAIL ) ) {
                        $email = sanitize_email( $url );
                        if ( $email !== '' ) {
                            $url = 'mailto:' . $email;
                        }
                    } elseif ( preg_match( '/^[0-9+\s().\-\.]{5,}$/', $url ) === 1 ) {
                        // Phone -> tel:
                        $normalized_phone = preg_replace( '/[^0-9+]/', '', $url );
                        if ( $normalized_phone !== '' ) {
                            $url = 'tel:' . $normalized_phone;
                        }
                    } else {
                        // Relative URL -> absolute
                        $url = home_url( '/' ) . ltrim( $url, '/' );
                    }
                }

                $child_item_id = wp_update_nav_menu_item(
                    $menu_id,
                    0,
                    array(
                        'menu-item-title'       => $name,
                        'menu-item-url'         => $url,
                        'menu-item-type'        => 'custom',
                        'menu-item-status'      => 'publish',
                        'menu-item-parent-id'   => (int) $parent_item_id,
                    )
                );
                if ( is_wp_error( $child_item_id ) ) {
                    puffergo_log( 'Footer menu child item failed: ' . $child_item_id->get_error_message(), 'AI Site Builder' );
                }
            }
        }
    }

     /**
     * 创建单个页面 (TAILWIND MODE)
     */

    
    private function create_tailwind_page( $page, array $site_pages = array() ) {

        $page_name     = $page['name'] ?? 'Untitled';
        $slug          = sanitize_title( $page['path'] ?: $page_name );
        $html          = $page['html'] ?? '';
        $css           = $page['css'] ?? '';
        $base_scope_id = $page['scopeId'] ?? '';

        puffergo_log( '[Phase 2] Creating multi-block page: ' . $page_name );
        puffergo_log( '[Phase 2] HTML length: ' . strlen( $html ) . ' characters' );

        // 🎯 PHASE 2: Split HTML into multiple sections
        $sections = $this->split_html_into_sections( $html );
        puffergo_log( '[Phase 2] Split into ' . count( $sections ) . ' sections' );
        
        // Create content with multiple blocks (one per section)
        $content = '';
        foreach ($sections as $index => $section) {
            // Generate unique scope ID for each section
            $section_scope_id = $base_scope_id . '-s' . ($index + 1);
            
            puffergo_log('[Phase 2] Section ' . ($index + 1) . ': ' . $section['name'] . ' (' . strlen($section['html']) . ' chars)');
            
            // Rewrite CSS so selectors target this section's scope (not the original page scope).
            // Otherwise styles from Step 4 AI edits would not apply on the edit page.
            $section_css = $this->rewrite_css_scope_for_section($css, $base_scope_id, $section_scope_id);
            
            // Create block for this section
            $content .= $this->create_tailwind_block_content(
                $section['html'],
                $section_css,
                $section_scope_id
            );
            
            // Add spacing between blocks
            $content .= "\n\n";
        }

        // Step4 只创建为草稿，Step5 发布后才上线
        // wp_insert_post 会自动调用 wp_unslash() 移除斜杠，须用 wp_slash() 预先转义
        $page_id = wp_insert_post([
            'post_type'    => 'page',
            'post_title'   => $page_name,
            'post_name'    => $slug,
            'post_content' => wp_slash($content),
            'post_status'  => 'draft',
            'post_author'  => get_current_user_id(),
        ], true);

        if (is_wp_error($page_id)) {
            // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- WP_Error message for internal exception
            throw new Exception($page_id->get_error_message());
        }

        puffergo_log( '[Phase 2] Page created successfully with ID: ' . $page_id );

        // Use plugin full-page template (header/footer not from theme)
        update_post_meta( $page_id, '_wp_page_template', 'puffergo-fullpage.php' );

        // SEO：Step3 的 title / description / 1 核心 + 5 长尾 → RankMath（优先）+ Yoast
        $seo = isset( $page['seo'] ) && is_array( $page['seo'] ) ? $page['seo'] : array();
        $this->save_seo_meta_for_page( $page_id, $seo );

        // Add to PufferGo's own primary menu.
        $this->add_page_to_puffergo_primary( $page_id, $page_name );

        return $page_id;
    }

    /**
     * 将 Step3 的 SEO 数据写入页面 meta：RankMath 优先，Yoast 兼容。
     * 关键词：1 个 coreKeyword + 最多 5 个 longTailKeyword，共 6 个。
     *
     * @param int   $page_id 页面 ID。
     * @param array $seo     step3 的 seo 对象：title, description, coreKeywords[], longTailKeywords[]。
     */
    private function save_seo_meta_for_page($page_id, $seo) {
        if (empty($seo) || ! is_array($seo)) {
            return;
        }

        $title = isset($seo['title']) && is_string($seo['title'])
            ? sanitize_text_field(wp_unslash($seo['title']))
            : '';
        $description = isset($seo['description']) && is_string($seo['description'])
            ? sanitize_textarea_field(wp_unslash($seo['description']))
            : '';

        $core = isset($seo['coreKeywords']) && is_array($seo['coreKeywords'])
            ? array_slice(array_map('sanitize_text_field', array_map('wp_unslash', $seo['coreKeywords'])), 0, 1)
            : array();
        $long_tail = isset($seo['longTailKeywords']) && is_array($seo['longTailKeywords'])
            ? array_slice(array_map('sanitize_text_field', array_map('wp_unslash', $seo['longTailKeywords'])), 0, 5)
            : array();
        $keywords = array_filter(array_merge($core, $long_tail));
        $focus_keyword_string = implode(', ', $keywords);

        if ('' !== $title) {
            update_post_meta($page_id, 'rank_math_title', $title);
            update_post_meta($page_id, '_yoast_wpseo_title', $title);
        }
        if ('' !== $description) {
            update_post_meta($page_id, 'rank_math_description', $description);
            update_post_meta($page_id, '_yoast_wpseo_metadesc', $description);
        }
        if ('' !== $focus_keyword_string) {
            update_post_meta($page_id, 'rank_math_focus_keyword', $focus_keyword_string);
            update_post_meta($page_id, '_yoast_wpseo_focuskw', $focus_keyword_string);
        }
    }
    
    /**
     * 🎯 Phase 2: Split HTML into logical sections for multi-block architecture
     * 
     * @param string $html Full page HTML
     * @return array Array of sections with 'name' and 'html' keys
     */
    private function split_html_into_sections($html) {
        if (empty($html)) {
            return array();
        }
        
        $sections = array();
        
        // Load HTML into DOMDocument for parsing
        $dom = new DOMDocument();
        // Suppress warnings for malformed HTML
        libxml_use_internal_errors(true);
        
        // Add UTF-8 meta tag to ensure proper encoding
        $html_with_meta = '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body>' . $html . '</body></html>';
        $dom->loadHTML($html_with_meta, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        libxml_clear_errors();
        
        $body = $dom->getElementsByTagName('body')->item(0);
        if (!$body) {
            // Fallback: return entire HTML as one section
            return array(
                array(
                    'name' => 'Main Content',
                    'html' => $html,
                )
            );
        }
        
        // 🎯 CRITICAL FIX: Unwrap single wrapper div
        // If body has only 1 child and it's a generic wrapper (div/main), 
        // use its children instead to find the actual sections
        $target_node = $body;
        
        // Count actual element children (skip text/comment nodes)
        $element_children = array();
        foreach ($body->childNodes as $child) {
            if ($child->nodeType === XML_ELEMENT_NODE) {
                $element_children[] = $child;
            }
        }
        
        if (count($element_children) === 1) {
            $wrapper = $element_children[0];
            $wrapper_tag = strtolower($wrapper->nodeName);
            
            puffergo_log('[Phase 2] Found single wrapper: <' . $wrapper_tag . '>');
            
            // If it's a generic container (div, main), unwrap it
            if (in_array($wrapper_tag, array('div', 'main'), true)) {
                puffergo_log('[Phase 2] Unwrapping <' . $wrapper_tag . '>, using its children instead');
                $target_node = $wrapper; // Use wrapper's children
            }
        }
        
        // Strategy: Split by top-level semantic tags
        $section_tags = array('header', 'nav', 'main', 'section', 'article', 'aside', 'footer');
        $section_count = array();
        
        foreach ($target_node->childNodes as $node) {
            if ($node->nodeType !== XML_ELEMENT_NODE) {
                continue; // Skip text nodes, comments, etc.
            }
            
            $tag_name = strtolower($node->nodeName);
            
            // Check if this is a semantic section tag
            if (in_array($tag_name, $section_tags, true)) {
                // Get section name from tag and class
                $section_name = $this->get_section_name($node, $section_count);
                
                // Get HTML for this node
                $section_html = $dom->saveHTML($node);
                
                $sections[] = array(
                    'name' => $section_name,
                    'html' => $section_html,
                    'tag'  => $tag_name,
                );
            } else {
                // For non-semantic tags (div, etc.), group them as "Content Section"
                $section_html = $dom->saveHTML($node);
                $sections[] = array(
                    'name' => 'Content Section',
                    'html' => $section_html,
                    'tag'  => $tag_name,
                );
            }
        }
        
        // If no sections found, return entire HTML as one section
        if (empty($sections)) {
            $sections[] = array(
                'name' => 'Main Content',
                'html' => $html,
                'tag'  => 'div',
            );
        }
        
        return $sections;
    }
    
    /**
     * Get a human-readable name for a section
     * 
     * @param DOMElement $node The DOM node
     * @param array &$section_count Counter for section types
     * @return string Section name
     */
    private function get_section_name($node, &$section_count) {
        $tag_name = strtolower($node->nodeName);
        
        // Initialize counter for this tag if not exists
        if (!isset($section_count[$tag_name])) {
            $section_count[$tag_name] = 0;
        }
        $section_count[$tag_name]++;
        
        // Try to get a descriptive name from common attributes
        $name = null;
        
        // Check ID attribute
        if ($node->hasAttribute('id')) {
            $id = $node->getAttribute('id');
            $name = ucwords(str_replace(array('-', '_'), ' ', $id));
        }
        
        // Check class attribute for common patterns
        if (!$name && $node->hasAttribute('class')) {
            $classes = explode(' ', $node->getAttribute('class'));
            foreach ($classes as $class) {
                if (preg_match('/(hero|cta|feature|about|contact|footer|header|pricing|testimonial|faq)/i', $class, $matches)) {
                    $name = ucfirst($matches[1]);
                    break;
                }
            }
        }
        
        // Fallback: Use tag name with counter
        if (!$name) {
            $name = ucfirst($tag_name);
            if ($section_count[$tag_name] > 1) {
                $name .= ' ' . $section_count[$tag_name];
            }
        }
        
        return $name;
    }

    /**
     * Rewrite CSS so selectors use the section scope instead of the page scope.
     * When we split one page into multiple blocks, each block gets a scope like pg--xxx-s1, pg--xxx-s2.
     * The original CSS was compiled for pg--xxx, so selectors must be rewritten or styles won't apply.
     *
     * @param string $css                Full page CSS (selectors use base_scope_id).
     * @param string $base_scope_id      Original page scope (e.g. pg--irfg2dgf).
     * @param string $section_scope_id   Section scope for this block (e.g. pg--irfg2dgf-s1).
     * @return string CSS with base scope class replaced by section scope class.
     */
    private function rewrite_css_scope_for_section($css, $base_scope_id, $section_scope_id) {
        if (empty($base_scope_id) || empty($css)) {
            return $css;
        }
        // Match .base_scope_id when used as a CSS class (followed by space, dot, colon, bracket, comma, brace).
        // Use (?!-) to avoid replacing .pg--xxx-s1 with .pg--xxx-s1-s1 when processing section 1.
        $pattern = '/\.' . preg_quote($base_scope_id, '/') . '(?!-)(?=[\s.:\[,\{\}\)])/';
        return preg_replace($pattern, '.' . $section_scope_id, $css);
    }

    /**
     * 创建 tailwind-container 块内容
     *
     * @param string $html      HTML内容
     * @param string $css       CSS内容
     * @param string $scope_id  作用域ID
     * @return string 序列化后的块内容
     */
    private function create_tailwind_block_content($html, $css, $scope_id) {
        // 确保输入是有效的 UTF-8 字符串
        $html = mb_convert_encoding($html, 'UTF-8', 'UTF-8');
        $css = mb_convert_encoding($css, 'UTF-8', 'UTF-8');
        $scope_id = mb_convert_encoding($scope_id, 'UTF-8', 'UTF-8');

        // 构建属性数组
        $attributes = array(
            'content'   => $html,
            'customCss' => $css,
            'scopeId'   => $scope_id,
        );

        // 使用 wp_json_encode 正确编码（自动处理双引号、换行符等转义）
        $attributes_json = wp_json_encode($attributes, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

        // 防御性检查：如果编码失败，记录错误并返回空属性
        if ($attributes_json === false) {
            puffergo_log('[PufferGo] wp_json_encode failed. JSON error: ' . json_last_error_msg());
            $attributes_json = '{}';
        }

        $block_comment = '<!-- wp:puffergo/tailwind-container ' . $attributes_json . ' -->';

        // 拼接标准 WordPress 区块格式
        // 注意：CSS 不再直接嵌入到块内容中，而是在渲染时通过 wp_add_inline_style 添加
        return $block_comment .
               '<div class="wp-block-puffergo-tailwind-container ' . esc_attr($scope_id) . '">' .
               $html .
               '</div>' .
               '<!-- /wp:puffergo/tailwind-container -->';
    }

    /**
     * Step 5: 发布页面
     */
    public function publish_pages($request) {
        $params = $request->get_json_params();
        $page_ids = $params['pageIds'] ?? array();
        
        if (empty($page_ids)) {
            return new WP_REST_Response([
                'success' => false,
                'message' => __('No pages specified for publishing', 'puffergo')
            ], 400);
        }
        
        $results = array();
        $success_count = 0;
        
        foreach ($page_ids as $page_id) {
            $result = wp_update_post(array(
                'ID' => $page_id,
                'post_status' => 'publish'
            ), true);
            
            if (!is_wp_error($result)) {
                $results[] = array(
                    'success' => true,
                    'pageId' => $page_id
                );
                $success_count++;
            } else {
                $results[] = array(
                    'success' => false,
                    'pageId' => $page_id,
                    'error' => $result->get_error_message()
                );
            }
        }
        
        return new WP_REST_Response([
            'success' => true,
            'data' => array(
                'results' => $results,
                'successCount' => $success_count
            )
        ], 200);
    }

    /**
     * 调用外部 workflow API 的通用方法
     */
    private function call_workflow_api($endpoint, $data) {
        $api_client = PufferGo_API_Client::get_instance();
        
        try {
            return $api_client->post(
                $endpoint,
                $data,
                array(
                    'timeout' => 205,
                    'log_prefix' => 'AI Site Builder'
                )
            );
        } catch (Exception $e) {
            puffergo_log('AI Site Builder: API调用失败 - ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * GET 请求到 workflow API（用于 profile-default 等）
     */
    private function call_workflow_api_get( $endpoint ) {
        $api_client = PufferGo_API_Client::get_instance();
        try {
            return $api_client->get(
                $endpoint,
                array(),
                array(
                    'timeout' => 30,
                    'log_prefix' => 'AI Site Builder'
                )
            );
        } catch ( Exception $e ) {
            puffergo_log( 'AI Site Builder: GET API 失败 - ' . $e->getMessage() );
            throw $e;
        }
    }
}