<?php
defined( 'ABSPATH' ) || exit;

class Jalpi_Editor {

    private static $instance = null;

    public static function instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        add_action( 'admin_menu',         [ $this, 'register_menu' ] );
        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_editor' ] );
    }

    public function register_menu() {
        add_menu_page(
            __( 'Jalpi Page Builder', 'jalpi-page-builder' ),
            __( 'Jalpi Page Builder', 'jalpi-page-builder' ),
            'edit_posts',
            'jalpi-page-builder-editor',
            [ $this, 'render_editor_page' ],
            'dashicons-layout',
            30
        );
    }

    public function render_editor_page() {
        // Read-only GET parameter used to select which post to edit.
        // Nonce is not required here because this is an admin menu page
        // (WordPress verifies admin access) and the value is validated
        // by capability check below. However, we verify a nonce when one
        // is present so direct links with a nonce are fully validated.
        $post_id = absint( $_GET['post_id'] ?? 0 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only display param, validated by current_user_can below

        if ( ! $post_id ) {
            $this->render_dashboard();
            return;
        }

        if ( ! current_user_can( 'edit_post', $post_id ) ) {
            wp_die( esc_html__( 'Permission denied.', 'jalpi-page-builder' ) );
        }

        $post = get_post( $post_id );
        if ( ! $post ) {
            echo '<div class="wrap"><p>' . esc_html__( 'Invalid post ID.', 'jalpi-page-builder' ) . '</p></div>';
            return;
        }

        // Restrict to enabled post types + internal types (e.g. jalpi_theme_tpl).
        $allowed_types   = (array) get_option( 'jalpi_enabled_post_types', [ 'page', 'post' ] );
        $internal_types  = (array) apply_filters( 'jalpi_internal_editor_post_types', [] );
        $allowed_types   = array_merge( $allowed_types, $internal_types );
        if ( ! in_array( $post->post_type, $allowed_types, true ) ) {
            wp_die( esc_html__( 'This post type is not supported by Jalpi Page Builder.', 'jalpi-page-builder' ) );
        }

        // Full-screen editor — just a React mount point.
        echo '<div id="jalpi-editor-root" data-post-id="' . esc_attr( $post_id ) . '"></div>';
    }

    private function render_dashboard() {
        $enabled_types = get_option( 'jalpi_enabled_post_types', [ 'page', 'post' ] );

        $posts = get_posts( [
            'post_type'      => $enabled_types,
            'post_status'    => [ 'publish', 'draft' ],
            'posts_per_page' => 50,
            'orderby'        => 'modified',
            'order'          => 'DESC',
        ] );

        echo '<div class="wrap">';
        echo '<h1>' . esc_html__( 'Jalpi Page Builder', 'jalpi-page-builder' ) . '</h1>';
        echo '<p>' . esc_html__( 'Select a page or post to edit with Jalpi Page Builder.', 'jalpi-page-builder' ) . '</p>';

        if ( empty( $posts ) ) {
            echo '<p>' . esc_html__( 'No pages or posts found. Create a page first, then use the "Edit with Jalpi Page Builder" button.', 'jalpi-page-builder' ) . '</p>';
        } else {
            echo '<table class="wp-list-table widefat fixed striped">';
            echo '<thead><tr>';
            echo '<th>' . esc_html__( 'Title', 'jalpi-page-builder' ) . '</th>';
            echo '<th>' . esc_html__( 'Type', 'jalpi-page-builder' ) . '</th>';
            echo '<th>' . esc_html__( 'Status', 'jalpi-page-builder' ) . '</th>';
            echo '<th>' . esc_html__( 'Modified', 'jalpi-page-builder' ) . '</th>';
            echo '<th>' . esc_html__( 'Action', 'jalpi-page-builder' ) . '</th>';
            echo '</tr></thead><tbody>';

            foreach ( $posts as $post ) {
                $editor_url = admin_url( 'admin.php?page=jalpi-page-builder-editor&post_id=' . $post->ID );
                echo '<tr>';
                echo '<td><strong>' . esc_html( $post->post_title ?: __( '(no title)', 'jalpi-page-builder' ) ) . '</strong></td>';
                echo '<td>' . esc_html( $post->post_type ) . '</td>';
                echo '<td>' . esc_html( $post->post_status ) . '</td>';
                echo '<td>' . esc_html( get_the_modified_date( 'Y-m-d', $post ) ) . '</td>';
                echo '<td><a href="' . esc_url( $editor_url ) . '" class="button button-primary">' . esc_html__( 'Edit with Jalpi Page Builder', 'jalpi-page-builder' ) . '</a></td>';
                echo '</tr>';
            }

            echo '</tbody></table>';
        }

        echo '</div>';
    }

    public function enqueue_editor( $hook ) {
        if ( 'toplevel_page_jalpi-page-builder-editor' !== $hook ) {
            return;
        }

        $post_id = absint( $_GET['post_id'] ?? 0 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only display param, validated by current_user_can below
        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
            return;
        }

        // Hide WordPress admin footer ("Thank you for creating with WordPress")
        add_filter( 'admin_footer_text', '__return_empty_string', 99 );
        add_filter( 'update_footer',     '__return_empty_string', 99 );

        // Load WordPress media library so wp.media() is available in the editor
        wp_enqueue_media( [ 'post' => $post_id ] );

        $asset_file  = JALPI_DIR . 'admin/editor/build/index.asset.php';
        $build_file  = JALPI_DIR . 'admin/editor/build/index.js';
        $deps        = [];
        // Use file mtime so the browser cache busts on every rebuild.
        $version     = file_exists( $build_file ) ? filemtime( $build_file ) : JALPI_VERSION;

        if ( file_exists( $asset_file ) ) {
            $asset = include $asset_file;
            $deps  = $asset['dependencies'] ?? [];
        }

        wp_enqueue_script(
            'jalpi-editor',
            JALPI_ADMIN_URL . 'editor/build/index.js',
            $deps,
            (string) $version,
            true
        );

        wp_enqueue_style(
            'jalpi-editor',
            JALPI_ADMIN_URL . 'editor/build/index.css',
            [],
            $version
        );

        // Fullscreen CSS — attached to the editor stylesheet via wp_add_inline_style
        // instead of a raw <style> tag in admin_head.
        wp_add_inline_style( 'jalpi-editor', $this->editor_fullscreen_css_string() );

        wp_localize_script( 'jalpi-editor', 'jalpiEditorConfig', [
            // Lets the inspector hide shop-only controls on sites without
            // WooCommerce rather than offering links that cannot work.
            'hasWoo'     => class_exists( 'WooCommerce' ),
            'postId'     => $post_id,                              // already absint()
            'apiUrl'     => esc_url_raw( rest_url( 'jalpi-page-builder/v1' ) ),
            'nonce'      => wp_create_nonce( 'wp_rest' ),
            'adminUrl'   => esc_url_raw( admin_url() ),
            'homeUrl'    => esc_url_raw( home_url() ),
            'previewUrl' => esc_url_raw( get_preview_post_link( $post_id ) ),
            'uploadUrl' => esc_url_raw( admin_url( 'upload.php' ) ),
            'assetsUrl' => esc_url_raw( JALPI_ASSETS_URL ),
            'pluginUrl' => esc_url_raw( JALPI_URL ),
            'version'   => sanitize_text_field( JALPI_VERSION ),
            'colors'    => $this->get_theme_colors(),
            'fonts'     => $this->get_available_fonts(),
            'designSystem' => Jalpi_Settings::get_design_system(),
            'canManageDesignSystem' => current_user_can( apply_filters( 'jalpi_design_system_capability', 'manage_options' ) ),
            'canUnfilteredHtml' => current_user_can( 'unfiltered_html' ),
            // Template list inlined — no REST call needed to list (avoids loopback hang).
            // bundled_slug is included so the editor can fetch bundled templates as
            // static JSON files (bypassing the REST API entirely for those too).
            'templateList' => $this->get_template_list(),
            // Nonce for the standalone template preview / thumbnail route.
            'previewNonce' => wp_create_nonce( Jalpi_Template_Preview::NONCE_ACTION ),
            'ajaxUrl'      => admin_url( 'admin-ajax.php' ),
        ] );
    }

    /**
     * No-op. Retained for backward compatibility. Fullscreen CSS is now
     * attached via wp_add_inline_style in enqueue_editor().
     */
    public function editor_fullscreen_css() {}

    /**
     * Return the fullscreen CSS string (no <style> wrapper).
     */
    private function editor_fullscreen_css_string(): string {
        return '#wpcontent, #wpbody, #wpbody-content { padding: 0 !important; margin: 0 !important; }
            #adminmenuwrap, #adminmenuback, #wpadminbar { display: none !important; }
            html.wp-toolbar { padding-top: 0 !important; }
            body { overflow: hidden !important; }';
    }

    private function get_template_list(): array {
        $cache_key = 'jalpi_editor_tpl_list';
        $cached    = get_transient( $cache_key );
        if ( is_array( $cached ) ) {
            return $cached;
        }

        $posts = get_posts( [
            'post_type'      => Jalpi_Templates::CPT,
            'post_status'    => 'publish',
            'posts_per_page' => 200,
            'orderby'        => 'date',
            'order'          => 'DESC',
        ] );
        $list = array_map( function ( WP_Post $p ) {
            $category     = get_post_meta( $p->ID, '_jalpi_tpl_category', true ) ?: '';
            $bundled_slug = get_post_meta( $p->ID, '_jalpi_bundled_slug', true ) ?: null;
            $tags         = get_post_meta( $p->ID, '_jalpi_tpl_tags', true );
            return [
                'id'             => $p->ID,
                'name'           => $p->post_title,
                'description'    => (string) $p->post_excerpt,
                'type'           => get_post_meta( $p->ID, '_jalpi_tpl_type', true ) ?: 'section',
                'category'       => $category,
                'category_label' => Jalpi_Templates::CATEGORIES[ $category ] ?? '',
                'thumbnail'      => get_post_meta( $p->ID, '_jalpi_tpl_thumbnail', true ) ?: '',
                'bundled_slug'   => $bundled_slug,
                'tags'           => is_array( $tags ) ? array_values( $tags ) : [],
                'source'         => 'user',
                'readonly'       => false,
            ];
        }, $posts );

        // Merge the Starter Site kits so HOOPS / NOVA / PULSE and their pages
        // appear in the picker alongside saved templates. These are read from
        // JSON files, so no extra query and nothing to keep in sync.
        $list = array_merge( $list, Jalpi_Kit_Templates::all( false ) );

        set_transient( $cache_key, $list, HOUR_IN_SECONDS );
        return $list;
    }

    private function get_theme_colors() {
        $theme_json = WP_Theme_JSON_Resolver::get_merged_data();
        $settings   = $theme_json->get_settings();
        $colors     = $settings['color']['palette']['theme'] ?? [];
        $result     = [];
        foreach ( $colors as $color ) {
            $hex = Jalpi_Sanitizer::sanitize_color( $color['color'] ?? '' );
            if ( ! $hex ) {
                continue;
            }
            $result[] = [
                'name'  => sanitize_text_field( $color['name'] ?? '' ),
                'color' => $hex,
                'slug'  => sanitize_key( $color['slug'] ?? '' ),
            ];
        }

        if ( empty( $result ) ) {
            $result = [
                [ 'name' => 'Black',  'color' => '#000000', 'slug' => 'black'  ],
                [ 'name' => 'White',  'color' => '#ffffff', 'slug' => 'white'  ],
                [ 'name' => 'Primary','color' => '#0073aa', 'slug' => 'primary'],
                [ 'name' => 'Gray',   'color' => '#6b7280', 'slug' => 'gray'   ],
            ];
        }

        return $result;
    }

    private function get_available_fonts() {
        $fonts  = Jalpi_Settings::get_font_options();
        $google = Jalpi_Google_Fonts::instance();

        // Enrich each entry with a source field so the editor can distinguish
        // system fonts from Google fonts (useful for live preview loading).
        foreach ( $fonts as &$entry ) {
            if ( isset( $entry['source'] ) ) {
                continue;
            }
            // Extract family name from value like '"Roboto", sans-serif'
            if ( preg_match( '/^"([^"]+)"/', $entry['value'] ?? '', $m ) ) {
                $entry['source'] = $google->get_font( $m[1] ) ? 'google' : 'system';
            } else {
                $entry['source'] = 'system';
            }
        }
        unset( $entry );

        return apply_filters( 'jalpi_settings_font_options', $fonts );
    }
}
