<?php

/**
 * Meta Box Handler
 *
 * Handles the SEO meta box in the post editor.
 *
 * @package ProRank\SEO\Admin
 * @since   0.1.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Admin;

use ProRank\SEO\Plugin;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}


/**
 * MetaBox class
 */


class MetaBox {
    /**
     * Resolve a cache-busting version for the meta-box entry script.
     *
     * The generated asset file still uses a static version string, which leaves
     * old ESM import graphs cached in the browser. Filemtime is enough here.
     */
    public static function resolve_meta_box_script_version(): string {
        static $version = null;
        if ($version !== null) {
            return $version;
        }

        $script_path = PRORANK_PLUGIN_DIR . 'build/meta-box.js';
        if (file_exists($script_path)) {
            $version = (string) filemtime($script_path);
            return $version;
        }

        $asset_file = PRORANK_PLUGIN_DIR . 'build/meta-box.asset.php';
        $asset_data = file_exists($asset_file) ? require $asset_file : [];
        $version = (string) ($asset_data['version'] ?? PRORANK_VERSION);

        return $version;
    }

    /**
     * Resolve the Vite content-hashed meta-box CSS URL.
     *
     * Reads build/manifest.json once, finds the CSS file associated with the
     * meta-box entry point, and returns the full URL. Falls back to the
     * unhashed filename if the manifest is missing.
     *
     * Public + static so builder integrations (Elementor, Divi, BB) can reuse it.
     */
    public static function resolve_meta_box_css(): string {
        static $url = null;
        if ($url !== null) {
            return $url;
        }

        $build_dir = PRORANK_PLUGIN_DIR . 'build/';
        $build_url = PRORANK_PLUGIN_URL . 'build/';

        // Try manifest.json first
        $manifest_file = $build_dir . 'manifest.json';
        if (file_exists($manifest_file)) {
            $manifest = json_decode((string) file_get_contents($manifest_file), true);
            if (is_array($manifest)) {
                $entry = $manifest['src/editor/meta-box/index.jsx'] ?? null;
                if ($entry && !empty($entry['css'][0])) {
                    $url = $build_url . $entry['css'][0];
                    return $url;
                }
            }
        }

        // Fallback: glob for meta-box-*.css
        $glob = glob($build_dir . 'meta-box-*.css');
        if (!empty($glob)) {
            $url = $build_url . basename($glob[0]);
            return $url;
        }

        // Last resort: unhashed name (will 404 with Vite builds)
        $url = $build_url . 'meta-box.css';
        return $url;
    }

    /**
     * Plugin instance
     *
     * @var Plugin
     */
    private Plugin $plugin;

    /**
     * Constructor
     *
     * @param Plugin $plugin Plugin instance.
     */
    public function __construct(Plugin $plugin) {
        $this->plugin = $plugin;
    }

    /**
     * Initialize meta box
     *
     * @return void
     */
    public function init(): void {
        add_action('add_meta_boxes', [$this, 'add_meta_box']);
        add_action('admin_enqueue_scripts', [$this, 'enqueue_assets']);
    }

    /**
     * Add meta box to post editor
     *
     * @return void
     */
    public function add_meta_box(): void {
        $screen = get_current_screen();
        
        // Only add to post edit screens
        if (!$screen || $screen->base !== 'post') {
            return;
        }

        // Get publicly queryable post types
        $post_types = get_post_types(['public' => true], 'names');

        // Respect per-post-type meta box settings
        $post_types = array_values(array_filter($post_types, function ($post_type) {
            return $this->is_meta_box_enabled($post_type);
        }));

        if (empty($post_types)) {
            return;
        }
        
        add_meta_box(
            'prorank-seo-meta-box',
            __('ProRank SEO', 'prorank-seo'),
            [$this, 'render_meta_box'],
            $post_types,
            'normal',
            'high'
        );
    }

    /**
     * Render meta box content
     *
     * @param \WP_Post $post Current post object.
     * @return void
     */
    public function render_meta_box(\WP_Post $post): void {
        // Output container for React app
        echo '<div id="prorank-seo-metabox-root"></div>';
        
        // Add nonce field for security
        wp_nonce_field('prorank_seo_metabox', 'prorank_seo_metabox_nonce');
    }

    /**
     * Enqueue meta box assets
     *
     * @param string $hook Current admin page hook.
     * @return void
     */
    public function enqueue_assets(string $hook): void {
        // Only load on post edit screens
        if (!in_array($hook, ['post.php', 'post-new.php'], true)) {
            return;
        }

        $screen = get_current_screen();
        if (!$screen || $screen->base !== 'post') {
            return;
        }

        // Check if we're on a supported post type
        $post_type = $screen->post_type;
        $public_post_types = get_post_types(['public' => true], 'names');
        
        if (!in_array($post_type, $public_post_types, true)) {
            return;
        }

        if (!$this->is_meta_box_enabled($post_type)) {
            return;
        }

        // Enqueue meta box script from build directory
        $script_url = PRORANK_PLUGIN_URL . 'build/meta-box.js';

        // Get version from asset file if available
        $asset_file = PRORANK_PLUGIN_DIR . 'build/meta-box.asset.php';
        $asset_data = file_exists($asset_file) ? require $asset_file : [];
        $dependencies = $asset_data['dependencies'] ?? ['wp-element', 'wp-components', 'wp-i18n', 'wp-data', 'wp-api-fetch', 'wp-dom-ready', 'lodash'];
        $version = self::resolve_meta_box_script_version();

        wp_enqueue_script(
            'prorank-seo-meta-box',
            $script_url,
            $dependencies,
            $version,
            true
        );

        // Enqueue meta box CSS (Vite emits content-hashed filenames)
        $css_url = self::resolve_meta_box_css();
        if ($css_url) {
            wp_enqueue_style('prorank-seo-meta-box', $css_url, [], $version);
        }

        // Get current post
        global $post;
        $post_id = $post ? $post->ID : 0;

        $license_tier = 'free';
        $is_premium_active = false;

        // Localize script data
        wp_localize_script(
            'prorank-seo-meta-box',
            'prorankMetaboxData',
            [
                'licenseTier' => $license_tier,
                'isPremiumActive' => $is_premium_active,
                'postId' => $post_id,
                'postType' => $post_type,
                'nonce' => wp_create_nonce('prorank_seo_metabox'),
                'apiUrl' => rest_url('prorank-seo/v1'),
            ]
        );

        // Compatibility + safety: some bundles rely on window.prorankSettings being present.
        // Without it, checks like `window.prorankSettings?.license?.tier !== 'free'` become
        // true when the object is missing, which wrongly enables Pro-only UI and triggers 404s.
        $inline = 'window.prorankSettings = window.prorankSettings || {};';
        $inline .= 'window.prorankSettings.adminUrl = ' . wp_json_encode(admin_url()) . ';';
        $inline .= 'window.prorankSettings.upgradeUrl = ' . wp_json_encode('https://prorank.io/pricing') . ';';
        $inline .= 'window.prorankSettings.isPremiumActive = ' . ($is_premium_active ? 'true' : 'false') . ';';
        $inline .= 'window.prorankSettings.license = window.prorankSettings.license || {};';
        $inline .= 'window.prorankSettings.license.tier = ' . wp_json_encode($license_tier) . ';';
        wp_add_inline_script('prorank-seo-meta-box', $inline, 'before');

        // Set script translations
        wp_set_script_translations(
            'prorank-seo-meta-box',
            'prorank-seo',
            PRORANK_PLUGIN_DIR . 'languages'
        );
    }

    /**
     * Check if the SEO meta box is enabled for a post type.
     *
     * @param string $post_type Post type slug.
     * @return bool
     */
    private function is_meta_box_enabled(string $post_type): bool {
        $settings = get_option('prorank_seo_titles_meta', []);
        if (!is_array($settings) || empty($settings)) {
            $settings = get_option('prorank_titles_meta_settings', []);
        }

        if (!is_array($settings)) {
            return true;
        }

        $post_type_settings = $settings['post_type_' . $post_type] ?? [];
        if (!is_array($post_type_settings)) {
            return true;
        }

        return $post_type_settings['show_meta_box'] ?? true;
    }
}
