<?php

use Miruni\RestApi\Miruni_Block_Widgets_API;
use Miruni\RestApi\Miruni_Gutenberg_Blocks_API;
use Miruni\RestApi\Miruni_Update_Gutenberg_Blocks_API;
use Miruni\RestApi\Miruni_Theme_JSON_API;
use Miruni\RestApi\Miruni_Elementor_Schema_API;

/*
 * Plugin Name: Miruni
 * Description: Automate website feedback and edit requests directly in WordPress with AI. Cut down 80% of the time you spend managing your website.
 * Version: 1.0.16
 * Requires at least: 6.0
 * Requires PHP: 8.1
 * Author: Miruni
 * Author URI: https://miruni.io
 * License: GPL v3 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 */

// Prevent direct access to this file
if (!defined('ABSPATH')) {
    exit;
}

// Load the autoloader and file loader
require_once plugin_dir_path(__FILE__) . 'autoloader.php';
require_once plugin_dir_path(__FILE__) . 'file-loader.php';

// Register the autoloader
\Miruni\Miruni_Autoloader::register();

// Initialize the file loader
$loader = \Miruni\Miruni_File_Loader::get_instance();

// Register core files with dependencies
$loader->register('env', 'env.php');
$loader->register('api-endpoints', 'api-endpoints.php');
$loader->register('template-dependency-tracker', 'template-dependency-tracker.php');
$loader->register('newrelic', 'newrelic.php');
$loader->register('on-uninstall', 'on-uninstall.php');

// Register REST API files with dependencies
$loader->register('rest-api-status', 'rest-api/status.php');
$loader->register('rest-api-base', 'rest-api/base.php');
$loader->register('rest-api-referenced-posts', 'rest-api/referenced-posts.php', ['rest-api-base']);
$loader->register('rest-api-menu-settings', 'rest-api/menu-settings-api.php', ['rest-api-base']);
$loader->register('rest-api-generate-preview', 'rest-api/generate-preview-api.php', ['rest-api-base']);
$loader->register('rest-api-content-by-id', 'rest-api/content-by-id-api.php', ['rest-api-base']);
$loader->register('rest-api-block-widgets', 'rest-api/block-widgets.php', ['rest-api-base']);
$loader->register('rest-api-breakdance-global-block', 'rest-api/breakdance-global-block.php', ['rest-api-base']);
$loader->register('rest-api-gutenberg-blocks', 'rest-api/gutenberg-blocks-api.php', ['rest-api-base']);
$loader->register('rest-api-update-gutenberg-blocks', 'rest-api/update-gutenberg-blocks-api.php', ['rest-api-base']);
$loader->register('rest-api-elementor-schema', 'rest-api/elementor-schema-api.php', ['rest-api-base']);
$loader->register('rest-api-search-posts', 'rest-api/search-posts.php', ['rest-api-base']);
$loader->register('rest-api-search-media', 'rest-api/search-media.php', ['rest-api-base']);
$loader->register('miruni-theme-json-manager', 'theme-json/theme-json-manager.php');
$loader->register('rest-api-theme-json', 'rest-api/theme-json.php', ['rest-api-base', 'miruni-theme-json-manager']);
// Theme preview files
$loader->register('theme-preview-manager', 'theme-preview/theme-preview-manager.php');
$loader->register('elementor-theme-preview-manager', 'theme-preview/elementor-theme-preview-manager.php', ['theme-preview-manager']);
$loader->register('breakdance-theme-preview-manager', 'theme-preview/breakdance-theme-preview-manager.php', ['theme-preview-manager']);
$loader->register('theme-preview-factory', 'theme-preview/theme-preview-factory.php', ['theme-preview-manager', 'elementor-theme-preview-manager']);
$loader->register('preview-theme-builder', 'theme-preview/preview-theme-builder.php');
$loader->register('miruni-gutenberg-manager', 'gutenberg/gutenberg-manager.php');
// Register the Draft Manager
$loader->register('draft-manager-change-result', 'draft-manager/change-result.php');
$loader->register('draft-manager', 'draft-manager/draft-manager.php');
$loader->register('draft-manager-factory', 'draft-manager/elementor-draft-manager.php', ['draft-manager']);
$loader->register('draft-manager-breakdance', 'draft-manager/breakdance-draft-manager.php', ['draft-manager']);

//
$loader->register('miruni-block-widget', 'widgets/block-widget.php');
$loader->register('miruni-block-widget-manager', 'widgets/block-widget-manager.php', ['miruni-block-widget']);

// Elementor integration
$loader->register('miruni-elementor', 'elementor/miruni-elementor.php');
$loader->register('miruni-breakdance', 'breakdance/miruni-breakdance.php');
$loader->register('elementor-widget-manager', 'elementor/elementor-widget-manager.php', ['miruni-elementor']);

// Kadence integration
$loader->register('miruni-kadence', 'kadence/kadence-manager.php');

// Page info classes
$loader->register('page-info-base', 'page-info/base.php');
$loader->register('page-info-wordpress', 'page-info/wordpress.php', ['page-info-base']);
$loader->register('page-info-elementor', 'page-info/elementor.php', ['page-info-base']);
$loader->register('page-info-breakdance', 'page-info/breakdance.php', ['page-info-base']);
$loader->register('page-info-factory', 'page-info/factory.php', ['page-info-wordpress', 'page-info-elementor']);

$loader->register('post-meta-utils', 'post-meta-utils.php');

$loader->register('miruni-notice', 'notice/free-trial-notice.php');
$loader->register('miruni-media-manager', 'media-manager/media-manager.php');
$loader->register('miruni-merge-syntax-operation', 'merge-syntax/operation.php');
$loader->register('miruni-merge-syntax-parser', 'merge-syntax/miruni-merge-syntax.php', ['miruni-merge-syntax-operation']);
$loader->register('miruni-merge-syntax-handler', 'merge-syntax/handlers/handler.php', ['miruni-merge-syntax-operation']);
$loader->register('miruni-merge-syntax-attachment-handler-preview', 'merge-syntax/handlers/attachment-url-preview-handler.php', ['miruni-merge-syntax-handler', 'miruni-merge-syntax-operation']);
$loader->register('miruni-merge-syntax-attachment-handler-publish', 'merge-syntax/handlers/attachment-url-publish-handler.php', ['miruni-merge-syntax-handler', 'miruni-merge-syntax-operation']);

$loader->register('miruni-merge-syntax-processor', 'merge-syntax/processor.php', ['miruni-merge-syntax-handler', 'miruni-merge-syntax-operation']);
$loader->register('miruni-merge-syntax', 'merge-syntax/process.php', ['miruni-merge-syntax-processor', 'miruni-merge-syntax-attachment-handler', 'miruni-merge-syntax-parser']);
// Load all registered files with dependencies resolved
$loader->load_all();

use Miruni\ThemePreview\Miruni_Theme_Preview_Factory;
use Miruni\RestApi\Miruni_Referenced_Posts_API;
use Miruni\PageInfo\Miruni_Page_Info_Factory;
use Miruni\RestApi\Miruni_Menu_Settings_API;
use Miruni\RestApi\Miruni_Content_By_Id_API;
use Miruni\RestApi\Miruni_Breakdance_Global_Block_API;
use Miruni\RestApi\Miruni_Search_Posts_API;
use Miruni\RestApi\Miruni_Search_Media_API;


/**
 * Initialize Miruni components
 */
function miruni_init(): void
{
    Miruni_Referenced_Posts_API::setup();
    Miruni_Menu_Settings_API::setup();
    Miruni_Content_By_Id_API::setup();
    Miruni_Block_Widgets_API::setup();
    Miruni_Breakdance_Global_Block_API::setup();
    Miruni_Gutenberg_Blocks_API::setup();
    Miruni_Update_Gutenberg_Blocks_API::setup();
    Miruni_Search_Posts_API::setup();
    Miruni_Search_Media_API::setup();
    Miruni_Theme_JSON_API::setup();
    Miruni_Elementor_Schema_API::setup();
    new Miruni_API_Endpoints();

    // Initialize the appropriate theme preview manager

    Miruni_Theme_Preview_Factory::register_maybe_use_preview_theme();
}

// Hook the initialization function to WordPress init
add_action('init', 'miruni_init');

/**
 * Deactivation hook
 */
function miruni_deactivate(): void
{
    // Deactivation code here
    uninstall_miruni();
    flush_rewrite_rules();
}
register_deactivation_hook(__FILE__, 'miruni_deactivate');

// @phpstan-ignore missingType.parameter
function miruni_log($message): void
{
    if (defined('WP_DEBUG') && WP_DEBUG === true) {
        if (is_array($message) || is_object($message)) {
            // Using wp_debug_log-compatible approach instead of direct error_log
            if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG === true) {
                error_log(print_r($message, true));
            }
        } else {
            if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG === true) {
                error_log($message);
            }
        }
    }
}

$miruni_logo_svg = "data:image/svg+xml;base64, ";


/**
 * Get the plugin menu slug, with fallback to 'miruni'
 */
function miruni_get_menu_slug(): string
{
    return miruni_get_env_var("PLUGIN_SLUG") ?? 'miruni';
}

/**
 * Add a menu item to the admin dashboard
 */
function miruni_add_menu_item(): void
{
    $override_logo_url = miruni_get_env_var("LOGO_IMG_URL");
    $override_plugin_name = miruni_get_env_var("PLUGIN_NAME");
    $menu_slug = miruni_get_menu_slug();

    global $miruni_logo_svg;
    add_menu_page(
        page_title: $override_plugin_name ?? 'Miruni', // Page title
        menu_title: $override_plugin_name ?? 'Miruni', // Menu title
        capability: 'manage_options',  // Capability required to see this option
        menu_slug: $menu_slug, // Menu slug
        callback: 'miruni_display_page', // Function to output content
        icon_url: $override_logo_url ?? $miruni_logo_svg, // Icon URL (escaped)
    );

    // Add submenu pages that will be handled by React
    add_submenu_page(
        $menu_slug,                // Parent slug - use dynamic slug
        'Dashboard',             // Page title
        'Dashboard',             // Menu title
        'manage_options',        // Capability
        $menu_slug,              // Menu slug (same as parent for default page)
        'miruni_display_page'    // Same display function
    );

    add_submenu_page(
        $menu_slug,              // Parent slug - use dynamic slug
        'Settings',
        'Settings',
        'manage_options',
        $menu_slug . '&view=settings',  // Note the view parameter
        'miruni_display_page'    // Same display function
    );

}
add_action('admin_menu', 'miruni_add_menu_item');

/**
 * Display the plugin page content
 */
function miruni_display_page(): void
{

    ?>
    <div id="miruni-admin-root"></div>
    <?php
}

/**
 * Sets free trial options based on payment subscriptions
 * 
 * @param array<array{id: string|int, nodeId: string, freeTrialEnds: string|null, plan: array{id: string|int, nodeId: string, label: string}}> $payment_subscriptions
 * @return void
 */
function miruni_set_free_trial_options(array $payment_subscriptions): void
{
    if (defined('WP_DEBUG') && WP_DEBUG === true) {
        error_log("Setting free trial options: " . json_encode($payment_subscriptions));
    }
    update_option('miruni_is_trial', true);

    $trial_end_date = null;
    if (!empty($payment_subscriptions)) {
        foreach ($payment_subscriptions as $subscription) {
            if (isset($subscription['freeTrialEnds']) && $subscription['freeTrialEnds']) {
                $trial_end_date = $subscription['freeTrialEnds'];
                break;
            }
        }
    }
    if (defined('WP_DEBUG') && WP_DEBUG === true) {
        error_log("Trial end date: " . $trial_end_date);
    }

    if ($trial_end_date) {
        update_option('miruni_trial_end_date', $trial_end_date);

        // Calculate days remaining
        $now = new DateTime();
        $end = new DateTime($trial_end_date);
        $days_remaining = $now->diff($end)->days;

        update_option('miruni_days_remaining', $days_remaining);
    } else {
        delete_option('miruni_trial_end_date');
        delete_option('miruni_days_remaining');
    }
}

/**
 * Custom implementation of miruni_array_find to find the first element in an array that passes a test
 *
 * @param array<mixed> $array The input array
 * @param callable $callback The test function to run on each element
 * @return mixed|null The first matching element or null if none found
 */
function miruni_array_find(array $array, callable $callback): mixed
{
    foreach ($array as $key => $value) {
        if ($callback($value, $key, $array)) {
            return $value;
        }
    }
    return null;
}

/**
 * Initialize WordPress login before admin pages load
 */
function miruni_init_wordpress_login(): void
{
    // Only proceed if we're in the Miruni admin pages
    if (!is_admin()) {
        return;
    }

    // Check and sanitize the 'page' parameter properly
    $page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
    $menu_slug = miruni_get_menu_slug();

    if (empty($page) || strpos($page, $menu_slug) !== 0) {
        return;
    }

    try {
        $miruni_service = new Miruni_Service();
        $keys = miruni_get_api_key_and_secret_key();
        $domain = wp_parse_url(get_site_url(), PHP_URL_HOST);

        if (!$domain) {
            do_action('miruni_plugin_error', new Exception("Domain not found"), [
                'context' => 'miruni_init_wordpress_login',
                'operation' => "Getting domain",
                'user_id' => get_current_user_id()
            ]);
            return;
        }

        // Call the wordpress_login function
        $login_response = $miruni_service->wordpress_login(
            $domain,
            false,
            $keys['api_key'],
            $keys['snippet_secret_key']
        );
        if (!$login_response) {
            return;
        }

        // @phpstan-ignore isset.offset
        $wp_login_data = isset($login_response['data']) && isset($login_response['data']['wordpressLogin']) ? $login_response['data']['wordpressLogin'] : null;

        $snippet_workspace_id = $wp_login_data['snippet']['workspaceId'] ?? null;


        // Safely access workspaces data
        $workspaces = isset($wp_login_data['workspaces']) && isset($wp_login_data['workspaces']['nodes'])
            ? ($wp_login_data['workspaces']['nodes'])
            : [];

        $snippet_workspace = miruni_array_find($workspaces, function ($workspace) use ($snippet_workspace_id) {
            return $workspace['id'] === $snippet_workspace_id;
        });

        if (!$snippet_workspace) {
            do_action('miruni_plugin_error', new Exception("Snippet workspace not found"), [
                'context' => 'miruni_init_wordpress_login',
                'operation' => "Getting snippet workspace",
                'user_id' => get_current_user_id()
            ]);
            return;
        }

        if ($snippet_workspace_id && $snippet_workspace["subscriptionStatus"] === "FREE_TRIAL") {
            $payment_subscriptions = $miruni_service->get_workspace_payment_subscriptions($snippet_workspace_id);
            miruni_set_free_trial_options($payment_subscriptions);
        } else {
            // Not a trial, update options accordingly
            update_option('miruni_is_trial', false);
            delete_option('miruni_trial_end_date');
            delete_option('miruni_days_remaining');
        }

        // Store the response for later use
        set_transient('miruni_wordpress_login_response', $login_response, 60 * 60);
    } catch (Exception $e) {

        do_action('miruni_plugin_error', $e, [
            'context' => 'miruni_init_wordpress_login',
            'operation' => "WordPress login initialization",
            'user_id' => get_current_user_id(),
            'page' => $page
        ]);
        // Log the error but don't disrupt the admin experience
        miruni_log('[Miruni] WordPress login initialization error: ' . $e->getMessage());
        // Store the error message
        set_transient('miruni_wordpress_login_error', $e->getMessage(), 60 * 60);
        // clear the response
        delete_transient('miruni_wordpress_login_response');
    }
}

add_action('admin_init', 'miruni_init_wordpress_login');

function miruni_admin_enqueue_scripts(string $hook): void
{
    // Simple log to test the plugin
    miruni_log('----------------------------------------');
    miruni_log(sprintf('[Miruni] START - Plugin loaded on hook: %s', $hook));

    $menu_slug = miruni_get_menu_slug();
    $expected_hook = 'toplevel_page_' . $menu_slug;

    if ($expected_hook !== $hook) {
        return;
    }

    wp_enqueue_script(
        'miruni-admin-runtime',
        plugins_url('admin/js/runtime.js', __FILE__),
        ['wp-element'],
        null,
        true
    );


    wp_enqueue_script(
        'miruni-admin',
        plugins_url('admin/js/admin.js', __FILE__),
        ['wp-element'],
        null,
        true
    );

    $current_user = wp_get_current_user();
    $keys = miruni_get_api_key_and_secret_key();

    // Get the WordPress login response data
    $login_response = get_transient('miruni_wordpress_login_response');
    $login_error = get_transient('miruni_wordpress_login_error');

    // Using proper debug logging
    if (defined('WP_DEBUG') && WP_DEBUG === true) {
        error_log("MIRUNI_API_ENDPOINT: " . miruni_get_env_var('MIRUNI_API_ENDPOINT'));
        error_log("miruni_get_api_url: " . miruni_get_api_url());
    }

    wp_localize_script('miruni-admin', 'miruniData', array(
        'pluginLogo' => miruni_get_env_var('LOGO_IMG_URL'),
        'pluginSlug' => miruni_get_menu_slug(),
        'pluginName' => miruni_get_env_var('PLUGIN_NAME'),
        'ajaxUrl' => admin_url('admin-ajax.php'),
        'adminUrl' => admin_url('admin.php'),
        'snippetApiKey' => $keys['api_key'],
        'snippetSecretKey' => $keys['snippet_secret_key'],
        'cssUrl' => plugins_url('css/styles.css', __FILE__),
        'stripePublicKey' => miruni_get_env_var('STRIPE_PUBLIC_KEY'),
        'miruniApiUrl' => miruni_get_env_var('MIRUNI_API_ENDPOINT'), // The url to the Miruni graphql proxy
        'miruniWebappUrl' => miruni_get_env_var('MIRUNI_WEBAPP_ENDPOINT'), // The url to the Miruni webapp
        'miruniSnippetProxyUrl' => miruni_get_env_var('SNIPPET_API_ENDPOINT'), // The url to the Miruni snippet proxy
        'nonce' => wp_create_nonce('miruni-nonce'),
        'siteDomain' => wp_parse_url(get_site_url(), PHP_URL_HOST), // Extract domain only
        'auth0' => array(
            'domain' => miruni_get_env_var('AUTH0_DOMAIN'),
            'clientId' => miruni_get_env_var('AUTH0_CLIENT_ID'),
            'redirectUri' => miruni_get_env_var('AUTH0_REDIRECT_URI'),
            'audience' => miruni_get_env_var('AUTH0_AUDIENCE'),
        ),
        'currentUser' => array(
            'id' => $current_user->ID,
            'username' => $current_user->user_login,
            'email' => $current_user->user_email,
            'displayName' => $current_user->display_name,
            'roles' => $current_user->roles
        ),
        'posthogId' => miruni_get_env_var('POSTHOG_ID'),
        'wordpressLogin' => array(
            'response' => $login_response,
            'error' => $login_error
        ),
        "new" => true
    ));
}
add_action('admin_enqueue_scripts', 'miruni_admin_enqueue_scripts');

function miruni_enqueue_styles(): void
{
    wp_enqueue_style(
        'miruni-styles',
        plugins_url('css/fonts.css', __FILE__),
        array(),
        '1.0.0'
    );
}
add_action('admin_enqueue_scripts', 'miruni_enqueue_styles');



/**
 * Summary of miruni_extract_theme_mod_keys
 * @param string $file_content
 * @return array<string>
 */
function miruni_extract_theme_mod_keys($file_content)
{
    $theme_mod_keys = [];

    // Regular expression to match get_theme_mod calls
    // This pattern looks for get_theme_mod with single or double quotes around the key
    $pattern = "/get_theme_mod\(\s*['\"]([^'\"]+)['\"]/";

    // Find all matches
    preg_match_all($pattern, $file_content, $matches);

    if (!empty($matches[1])) {
        // Remove duplicates
        $theme_mod_keys = array_unique($matches[1]);
        // Sort keys alphabetically
        sort($theme_mod_keys);
    }

    return $theme_mod_keys;
}



/**
 * Get current page content and ID
 * @return array<mixed>|null
 */
function miruni_get_current_page_info(): ?array
{
    // Get page ID with different methods based on page type
    $page_id = null;

    // Method 1: Check if this is the blog page (posts page)
    if (is_home() && !is_front_page()) {
        $page_id = get_option('page_for_posts');
    }
    // Method 2: Check if this is a static front page
    elseif (is_front_page() && is_page()) {
        $page_id = get_option('page_on_front');
    }
    // Method 3: Standard WordPress way for singular pages/posts
    elseif (is_singular()) {
        $page_id = get_queried_object_id();
    }

    // Method 4: Fallback to get_the_ID() (but this might give wrong results as you experienced)
    if (!$page_id) {
        $page_id = get_the_ID();
    }

    // Method 5: Direct from global query
    if (!$page_id) {
        global $wp_query;
        $page_id = $wp_query->queried_object_id ?? null;
    }

    // Method 6: From URL parameter (as last resort)
    if (!$page_id && isset($_GET['page_id']) && is_numeric($_GET['page_id'])) {
        $page_id = (int) $_GET['page_id'];
    }


    $page_info_service = Miruni_Page_Info_Factory::create();
    $page_info = $page_info_service->get_page_info();

    if ($page_id) {
        $template = get_page_template_slug($page_id);
        $page_info['template'] = $template;

        $endpoints = [
            'search_posts' => Miruni_Search_Posts_API::get_rest_url(),
            'menu_settings' => Miruni_Menu_Settings_API::get_rest_url($page_id),
            'block_widgets' => Miruni_Block_Widgets_API::get_rest_url(),
            'content_by_id' => Miruni_Content_By_Id_API::get_rest_url($page_id),
            'breakdance_global_block' => Miruni_Breakdance_Global_Block_API::get_rest_url(),
            'gutenberg_blocks' => Miruni_Gutenberg_Blocks_API::get_rest_url($page_id),
            'update_gutenberg_blocks' => Miruni_Update_Gutenberg_Blocks_API::get_preview_single_block_update_rest_url($page_id),
            'theme_json' => Miruni_Theme_JSON_API::get_rest_url($page_id),
            'get_elementor_schema' => Miruni_Elementor_Schema_API::get_rest_url($page_id),
            'search_media' => Miruni_Search_Media_API::get_rest_url()
        ];
        $page_info['endpoints'] = $endpoints;
        $page_info['post_id'] = $page_id;
        $page_info['post_title'] = get_the_title($page_id);
    }

    return $page_info;
}

function miruni_add_miruni_footer_code(): void
{
    try {
        $api_key = miruni_get_api_key();
        $cdn_domain = miruni_get_env_var('SNIPPET_CDN_DOMAIN') . '/miruni_snippet.js';

        $page_info = miruni_get_current_page_info();

        $posthog_id = miruni_get_env_var('POSTHOG_ID');
        $override_img_url = miruni_get_env_var("LOGO_IMG_URL") ?? "";
        ?>
        <script>
            const params = new URLSearchParams(window.location.search);
            const miruniId = params.get('miruni_id') || localStorage.getItem('miruni_id') || null;
            if (params.has('miruni_id')) {
                localStorage.setItem('miruni_id', params.get('miruni_id'));
            }
            window.MIRUNI_PAGE_INFO = <?php echo wp_json_encode($page_info); ?>; const SNIPPET_API_KEY = '<?php echo esc_js($api_key ?? ""); ?>'; const SNIPPET_API_URL = '<?php echo esc_js(miruni_get_env_var('SNIPPET_API_ENDPOINT') ?? ""); ?>';
            const s = '<?php echo esc_url($cdn_domain); ?>'; let e = document.createElement("script"); e.type = "application/javascript", e.src = s, e.id = "miruni-snippet-script", e.setAttribute("data-api-key", SNIPPET_API_KEY), e.setAttribute("data-override-logo", '<?php echo esc_js($override_img_url); ?>'), e.setAttribute("data-api-url", SNIPPET_API_URL), e.setAttribute("data-miruni-id", miruniId ?? ""), e.setAttribute("data-posthog-id", '<?php echo esc_js($posthog_id ?? ""); ?>'), e.async = !0, document.head.appendChild(e)
        </script>
        <?php
    } catch (Throwable $e) {
        do_action('miruni_plugin_error', $e, [
            'context' => 'miruni_add_miruni_footer_code',
            'operation' => "Adding Miruni footer code",
            'user_id' => get_current_user_id()
        ]);
        // Output the error to the browser console
        ?>
        <script>     console.error("Miruni footer error: <?php echo addslashes($e->getMessage()); ?>");
        </script>
        <?php
    }
}
add_action('wp_footer', 'miruni_add_miruni_footer_code');

add_action('template_include', function ($template) {
    return $template;
});
