<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class IDVE_REST_API {

    private $blocks;
    private $renderer;
    private $css_generator;
    private $importer;
    private $ai;

    public function __construct( IDVE_Blocks $blocks, IDVE_Renderer $renderer, IDVE_CSS_Generator $css_gen, IDVE_Importer $importer, IDVE_AI $ai = null ) {
        $this->blocks        = $blocks;
        $this->renderer      = $renderer;
        $this->css_generator = $css_gen;
        $this->importer      = $importer;
        $this->ai            = $ai;
        add_action( 'rest_api_init', array( $this, 'register_routes' ) );
    }

    public function register_routes() {
        $ns = 'idve/v1';

        register_rest_route( $ns, '/save/(?P<post_id>\d+)', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'save' ),
            'permission_callback' => array( $this, 'check_permission' ),
            'args' => array(
                'post_id' => array( 'required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint' ),
            ),
        ) );

        register_rest_route( $ns, '/load/(?P<post_id>\d+)', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'load' ),
            'permission_callback' => array( $this, 'check_permission' ),
            'args' => array(
                'post_id'      => array( 'required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint' ),
                'force_import' => array( 'required' => false, 'type' => 'integer', 'default' => 0, 'sanitize_callback' => 'absint' ),
            ),
        ) );

        register_rest_route( $ns, '/autosave/(?P<post_id>\d+)', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'autosave' ),
            'permission_callback' => array( $this, 'check_permission' ),
            'args' => array(
                'post_id' => array( 'required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint' ),
            ),
        ) );

        register_rest_route( $ns, '/blocks', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'get_blocks' ),
            'permission_callback' => array( $this, 'check_permission' ),
        ) );

        register_rest_route( $ns, '/global-styles', array(
            array(
                'methods'             => 'GET',
                'callback'            => array( $this, 'get_global_styles' ),
                'permission_callback' => array( $this, 'check_permission' ),
            ),
            array(
                'methods'             => 'POST',
                'callback'            => array( $this, 'save_global_styles' ),
                'permission_callback' => array( $this, 'check_permission' ),
            ),
        ) );

        register_rest_route( $ns, '/global-classes', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'get_global_classes' ),
            'permission_callback' => array( $this, 'check_permission' ),
        ) );

        register_rest_route( $ns, '/ai/generate', array(
            'methods'             => 'POST',
            'callback'            => array( $this, 'ai_generate' ),
            'permission_callback' => array( $this, 'check_permission' ),
        ) );
    }

    public function check_permission() {
        return current_user_can( 'edit_posts' );
    }

    public function save( $request ) {
        $post_id = $request->get_param( 'post_id' );
        $body    = $request->get_json_params();

        if ( ! isset( $body['tree'] ) || ! isset( $body['tree']['sections'] ) ) {
            return new WP_Error( 'invalid_tree', __( 'Invalid tree structure.', 'insight-dezign-visual-editor' ), array( 'status' => 400 ) );
        }

        $tree = $body['tree'];
        $html = $this->renderer->render( $tree );
        $css  = $this->css_generator->generate( $tree );

        remove_action( 'save_post', array( IDVE_Core::instance()->editor, 'save_toggle' ) );
        wp_update_post( array(
            'ID'           => $post_id,
            'post_content' => $html,
        ) );

        update_post_meta( $post_id, '_idve_data', wp_slash( wp_json_encode( $tree ) ) );
        update_post_meta( $post_id, '_idve_css', wp_slash( $css ) );
        update_post_meta( $post_id, '_idve_active', '1' );
        update_post_meta( $post_id, '_idve_content_hash', md5( $html ) );
        delete_post_meta( $post_id, '_idve_autosave' );

        return rest_ensure_response( array(
            'success' => true,
            'html'    => $html,
            'css'     => $css,
        ) );
    }

    public function load( $request ) {
        $post_id      = $request->get_param( 'post_id' );
        $force_import = (bool) $request->get_param( 'force_import' );
        $json_raw     = get_post_meta( $post_id, '_idve_data', true );
        $tree         = null;
        $has_drift    = false;

        // Force import: skip stored tree, rebuild from current post_content.
        // Pass old tree so the importer can preserve settings for matching IDs.
        if ( $force_import ) {
            $post    = get_post( $post_id );
            $content = $post ? $post->post_content : '';
            $old_tree = null;
            if ( $json_raw ) {
                $old_tree = json_decode( $json_raw, true );
                if ( ! $old_tree || ! isset( $old_tree['sections'] ) ) {
                    $old_tree = null;
                }
            }

            if ( strpos( $content, 'idve-section' ) !== false ) {
                $tree = $this->importer->import( $content, $old_tree );
            } elseif ( ! empty( $content ) ) {
                $tree = array(
                    'sections' => array(
                        $this->importer->wrap_in_html_block( $content ),
                    ),
                );
            } else {
                $tree = array( 'sections' => array() );
            }
        } else {
            if ( $json_raw ) {
                $tree = json_decode( $json_raw, true );
            }

            if ( ! $tree || ! isset( $tree['sections'] ) ) {
                $post    = get_post( $post_id );
                $content = $post ? $post->post_content : '';

                if ( strpos( $content, 'idve-section' ) !== false ) {
                    $tree = $this->importer->import( $content );
                } elseif ( ! empty( $content ) ) {
                    $tree = array(
                        'sections' => array(
                            $this->importer->wrap_in_html_block( $content ),
                        ),
                    );
                } else {
                    $tree = array( 'sections' => array() );
                }
            } else {
                // Valid tree exists — check for drift.
                $stored_hash = get_post_meta( $post_id, '_idve_content_hash', true );
                $post        = get_post( $post_id );

                if ( ! $stored_hash ) {
                    // Legacy page: no hash stored yet. Render tree to HTML and compare.
                    $expected_html = $this->renderer->render( $tree );
                    $stored_hash   = md5( $expected_html );
                }

                $current_hash = $post ? md5( $post->post_content ) : '';
                $has_drift    = ( $stored_hash !== $current_hash );
            }
        }

        // Migrate stretch from rows to sections (pre-0.1.18 trees).
        if ( $tree && isset( $tree['sections'] ) ) {
            foreach ( $tree['sections'] as &$sec ) {
                if ( empty( $sec['rows'] ) ) {
                    continue;
                }
                foreach ( $sec['rows'] as &$row ) {
                    $s = isset( $row['settings'] ) ? $row['settings'] : array();
                    if ( ! empty( $s['stretch'] ) && 'default' !== $s['stretch'] ) {
                        if ( ! isset( $sec['settings'] ) ) {
                            $sec['settings'] = array();
                        }
                        $sec['settings']['stretch'] = $s['stretch'];
                        if ( ! empty( $s['contentMaxWidth'] ) ) {
                            $sec['settings']['contentMaxWidth'] = $s['contentMaxWidth'];
                        }
                        $row['settings']['stretch']         = 'default';
                        $row['settings']['contentMaxWidth']  = '';
                    }
                }
            }
            unset( $sec, $row );
        }

        $autosave = get_post_meta( $post_id, '_idve_autosave', true );
        $has_autosave = false;
        if ( $autosave ) {
            $autosave_tree = json_decode( $autosave, true );
            if ( $autosave_tree && isset( $autosave_tree['sections'] ) ) {
                $has_autosave = true;
            }
        }

        return rest_ensure_response( array(
            'success'      => true,
            'tree'         => $tree,
            'hasAutosave'  => $has_autosave,
            'hasDrift'     => $has_drift,
        ) );
    }

    public function autosave( $request ) {
        $post_id = $request->get_param( 'post_id' );
        $body    = $request->get_json_params();

        if ( ! isset( $body['tree'] ) ) {
            return new WP_Error( 'invalid_tree', __( 'Invalid tree.', 'insight-dezign-visual-editor' ), array( 'status' => 400 ) );
        }

        update_post_meta( $post_id, '_idve_autosave', wp_slash( wp_json_encode( $body['tree'] ) ) );

        return rest_ensure_response( array( 'success' => true ) );
    }

    public function get_blocks() {
        return rest_ensure_response( $this->blocks->get_editor_config() );
    }

    public function get_global_styles() {
        $css = get_option( 'idve_global_styles', '' );
        return rest_ensure_response( array( 'success' => true, 'css' => $css ) );
    }

    public function save_global_styles( $request ) {
        $body = $request->get_json_params();
        $css  = isset( $body['css'] ) ? wp_strip_all_tags( $body['css'] ) : '';

        update_option( 'idve_global_styles', $css );
        IDVE_Core::write_global_styles_file( $css );

        return rest_ensure_response( array( 'success' => true ) );
    }

    public function get_global_classes() {
        $css = get_option( 'idve_global_styles', '' );
        $classes = array();

        if ( ! empty( $css ) ) {
            // Only match standalone class selectors: ".classname {" — not compound ones like ".classname h2 {".
            preg_match_all( '/(?:^|[},])\s*\.([a-zA-Z_-][a-zA-Z0-9_-]*)\s*\{([^}]*)\}/m', $css, $matches, PREG_SET_ORDER );
            $seen = array();

            foreach ( $matches as $match ) {
                $name       = $match[1];
                $properties = trim( $match[2] );

                // Skip internal IDVE classes and duplicates.
                if ( strpos( $name, 'idve-' ) === 0 || isset( $seen[ $name ] ) ) {
                    continue;
                }
                $seen[ $name ] = true;

                $classes[] = array(
                    'name'       => $name,
                    'properties' => $properties,
                );
            }
        }

        return rest_ensure_response( array( 'success' => true, 'classes' => $classes ) );
    }

    public function ai_generate( $request ) {
        if ( ! idve_is_pro() ) {
            return new WP_Error( 'ai_pro_required', __( 'The AI Assistant requires a Pro license.', 'insight-dezign-visual-editor' ), array( 'status' => 403 ) );
        }

        if ( ! $this->ai || ! $this->ai->is_configured() ) {
            return new WP_Error( 'ai_not_configured', __( 'AI is not configured.', 'insight-dezign-visual-editor' ), array( 'status' => 400 ) );
        }

        $body   = $request->get_json_params();
        $prompt = isset( $body['prompt'] ) ? sanitize_textarea_field( $body['prompt'] ) : '';
        $mode   = isset( $body['mode'] ) ? sanitize_key( $body['mode'] ) : '';
        $context = isset( $body['context'] ) && is_array( $body['context'] ) ? $body['context'] : array();

        if ( empty( $prompt ) ) {
            return new WP_Error( 'ai_empty_prompt', __( 'Please enter a prompt.', 'insight-dezign-visual-editor' ), array( 'status' => 400 ) );
        }

        $result = $this->ai->generate( $prompt, $mode, $context );

        if ( is_wp_error( $result ) ) {
            return $result;
        }

        return rest_ensure_response( array(
            'success' => true,
            'data'    => $result,
        ) );
    }
}
