<?php

namespace WPSN\Modules\Editor;

use WPSN\Core\AbstractModule;
use WPSN\Core\Branding;
use WPSN\Core\UI;
use WPSN\Core\ModuleRegistry;
use WPSN\SEO\MetaKeys;
use WPSN\SEO\SeoMetaRepository;
use WPSN\Domain\SeoDocumentContext;
use WPSN\Modules\AI\AISecretsRepository;
use WPSN\Core\Capabilities;

defined('ABSPATH') || exit;

final class EditorModule extends AbstractModule
{
    public function id(): string
    {
        return 'editor';
    }

    public function name(): string
    {
        return __('Editor UX', 'wp-seo-next');
    }

    public function description(): string
    {
        return __('Gutenberg sidebar (SEO) + snippet preview.', 'wp-seo-next');
    }

    public function defaultEnabled(): bool
    {
        return true;
    }

    public function register(): void
    {
        add_action('enqueue_block_editor_assets', [$this, 'enqueueEditorAssets']);
        add_action('rest_api_init', [$this, 'registerRestRoutes']);
    }

    public function enqueueEditorAssets(): void
    {
        // Only for block editor.
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if ($screen && method_exists($screen, 'is_block_editor') && !$screen->is_block_editor()) {
            return;
        }

        $handle = 'wpsn-editor-sidebar';
        $src = WPSN_PLUGIN_URL . 'assets/editor/sidebar.js';

        /** @var ModuleRegistry $modules */
        $modules = $this->container->get('modules');
        $schemaEnabled = $modules->isEnabled('schema');
        $aiModuleEnabled = $modules->isEnabled('ai');
        $socialEnabled = $modules->isEnabled('social');
        $searchConsoleEnabled = $modules->isEnabled('search_console');
        $analysisEnabled = $modules->isEnabled('analysis');

        $hideAiUi = (bool) $this->settings->get('privacy.hide_ai_ui', false);

        // Global switch for admin-ajax.php usage (some shared hosts return 503).
        $ajaxEnabled = \WPSN\Core\AjaxMode::isEnabled($this->settings);


        // AI settings (even if module is disabled we can show UI hints).
        $aiLocalEnabled = (bool) $this->settings->get('ai.local.enabled', false);
        $aiExternalEnabled = (bool) $this->settings->get('ai.external.enabled', false);
        $titleMax = (int) $this->settings->get('ai.local.title_max_length', 60);
        $descMax  = (int) $this->settings->get('ai.local.description_max_length', 155);
        $kwLimit  = (int) $this->settings->get('ai.local.keywords_limit', 12);
        $noDrafts = (bool) $this->settings->get('ai.privacy.no_drafts', true);

        if ($hideAiUi) {
            // UI-only: hide all AI panels/actions in the editor.
            $aiModuleEnabled = false;
            $aiLocalEnabled = false;
            $aiExternalEnabled = false;
        }


        $secrets = new AISecretsRepository();
        $hasKey = $secrets->hasOpenAIKey();

        // White-label: customize how the sidebar is named in Gutenberg.
        $wlEnabled = (bool) $this->settings->get('white_label.enabled', false);
        $wlMenuTitle = trim((string) $this->settings->get('white_label.menu_title', ''));
        $wlBrand = Branding::brand($this->settings);
        $editorSidebarLabel = __('SEO', 'wp-seo-next');
        if ($wlEnabled) {
            $editorSidebarLabel = $wlMenuTitle !== '' ? $wlMenuTitle : ($wlBrand !== '' ? $wlBrand : $editorSidebarLabel);
        }

        wp_register_script(
            $handle,
            $src,
            [
                'wp-plugins',
                'wp-edit-post',
                'wp-blocks',
                'wp-block-editor',
                'wp-element',
                'wp-components',
                'wp-data',
                'wp-api-fetch',
                'wp-i18n',
            ],
            WPSN_VERSION,
            true
        );

        // Provide constants to JS.
        wp_add_inline_script(
            $handle,
            'window.WPSN_EDITOR = ' . wp_json_encode([
                'restPreviewPath' => '/wpsn/v1/preview',
                'restSuggestPath' => '/wpsn/v1/suggest',
                'restAIGeneratePath' => '/wpsn/v1/ai/generate',
                'restInternalLinksPath' => '/wpsn/v1/internal-links',
                'restInternalLinksApplyPath' => '/wpsn/v1/internal-links/apply',
                'restInternalLinksDismissPath' => '/wpsn/v1/internal-links/dismiss',
                'restGscPagePath' => '/wpsn/v1/gsc/page',
                'restBriefPath' => '/wpsn/v1/brief',
                'restBriefGeneratePath' => '/wpsn/v1/brief/generate',
                'restAnalysisPath' => '/wpsn/v1/analysis',
                'settingsUrl' => admin_url('admin.php?page=wp-seo-next'),
                'toolsAiUrl'  => admin_url('tools.php?page=wpsn-seo-ai'),
                'toolsLinksHubUrl' => admin_url('tools.php?page=wpsn-search-console&view=links'),
                'toolsGscUrl' => admin_url('tools.php?page=wpsn-search-console&view=data'),
                'toolsBriefUrl' => admin_url('tools.php?page=wpsn-search-console&view=brief'),
                'whiteLabel' => [
                    'enabled' => $wlEnabled,
                    'sidebarLabel' => $editorSidebarLabel,
                ],
                'gsc' => [
                    'canManage' => Capabilities::canManageGsc(),
                    'ajaxEnabled' => $ajaxEnabled,
                    // NOTE: The editor sidebar should avoid admin-ajax.php by default.
                    // We still expose these for backwards compatibility, but keep them empty when AJAX is disabled.
                    'ajaxUrl' => $ajaxEnabled ? admin_url('admin-ajax.php') : '',
                    // Matches Search Console admin AJAX nonce action.
                    'ajaxNonce' => $ajaxEnabled ? wp_create_nonce('wpsn_gsc_ajax') : '',
                    // Direct-first inspector link (admin-post redirect), avoids admin-ajax.php entirely.
                    'inspectUrlBase' => (string) add_query_arg([
                        'action' => 'wpsn_gsc_inspect_link',
                        'wpsn_nonce' => wp_create_nonce('wpsn_gsc_inspect_link'),
                    ], admin_url('admin-post.php')),
                ],
                'modules' => [
                    'schema' => $schemaEnabled,
                    'ai'     => $aiModuleEnabled,
                    'social' => $socialEnabled,
                    'searchConsole' => $searchConsoleEnabled,
                    'analysis' => $analysisEnabled,
                ],
                'sitemap' => [
                    'videoEnabled' => (bool) $this->settings->get('sitemap.video.enabled', false),
                    'videoMode' => (string) $this->settings->get('sitemap.video.mode', 'meta'),
                    'videoIncludeFeaturedThumbnail' => (bool) $this->settings->get('sitemap.video.include_featured_thumbnail', true),
                ],
                'metaKeys' => [
                    'title'        => MetaKeys::TITLE,
                    'description'  => MetaKeys::DESCRIPTION,
                    'canonical'    => MetaKeys::CANONICAL,
                    'robotsIndex'  => MetaKeys::ROBOTS_INDEX,
                    'robotsFollow' => MetaKeys::ROBOTS_FOLLOW,
                    'schemaType'   => MetaKeys::SCHEMA_TYPE,
                    'focusKeyword' => MetaKeys::FOCUS_KEYWORD,
                    'ogTitle'      => MetaKeys::OG_TITLE,
                    'ogDescription' => MetaKeys::OG_DESCRIPTION,
                    'ogImage'      => MetaKeys::OG_IMAGE,
                    'twitterTitle' => MetaKeys::TWITTER_TITLE,
                    'twitterDescription' => MetaKeys::TWITTER_DESCRIPTION,
                    'twitterImage' => MetaKeys::TWITTER_IMAGE,
                    'videoUrl' => MetaKeys::VIDEO_URL,
                    'videoTitle' => MetaKeys::VIDEO_TITLE,
                    'videoDescription' => MetaKeys::VIDEO_DESCRIPTION,
                    'videoThumbnail' => MetaKeys::VIDEO_THUMBNAIL,
                    'videoDuration' => MetaKeys::VIDEO_DURATION,
                ],
                'ai' => [
                    'localEnabled' => $aiLocalEnabled,
                    'externalEnabled' => $aiExternalEnabled,
                    'providerConfigured' => $hasKey,
                    'canUseExternal' => Capabilities::canUseAI(),
                    'titleMaxLength' => $titleMax,
                    'descriptionMaxLength' => $descMax,
                    'keywordsLimit' => $kwLimit,
                    'noDrafts' => $noDrafts,
                ],
            ]) . ';',
            'before'
        );

        wp_enqueue_script($handle);
    }

    public function registerRestRoutes(): void
    {
        register_rest_route('wpsn/v1', '/preview', [
            'methods'             => 'POST',
            'permission_callback' => function (\WP_REST_Request $request): bool {
                $postId = (int) $request->get_param('post_id');
                return $postId > 0 && current_user_can('edit_post', $postId);
            },
            'callback'            => function (\WP_REST_Request $request) {
                $postId = (int) $request->get_param('post_id');
                $metaIn = $request->get_param('meta');
                if (!is_array($metaIn)) {
                    $metaIn = [];
                }

                $allowed = [
                    MetaKeys::TITLE,
                    MetaKeys::DESCRIPTION,
                    MetaKeys::CANONICAL,
                    MetaKeys::ROBOTS_INDEX,
                    MetaKeys::ROBOTS_FOLLOW,
                    MetaKeys::OG_TITLE,
                    MetaKeys::OG_DESCRIPTION,
                    MetaKeys::OG_IMAGE,
                    MetaKeys::TWITTER_TITLE,
                    MetaKeys::TWITTER_DESCRIPTION,
                    MetaKeys::TWITTER_IMAGE,
                ];

                $overrides = [];
                foreach ($allowed as $key) {
                    if (array_key_exists($key, $metaIn)) {
                        $v = $metaIn[$key];
                        $overrides[$key] = is_scalar($v) ? (string) $v : '';
                    }
                }

                $ctx = new SeoDocumentContext(
                    SeoDocumentContext::TYPE_SINGULAR,
                    $postId,
                    get_post_type($postId) ?: null,
                    get_permalink($postId) ?: home_url('/'),
                    1
                );

                /** @var SeoMetaRepository $repo */
                $repo = $this->container->get('meta_repo');
                $meta = $repo->forContextWithOverrides($ctx, $overrides);

                return rest_ensure_response([
                    'title'       => $meta->title,
                    'description' => $meta->description,
                    'canonical'   => $meta->canonical,
                    'robots'      => $meta->robots,
                    'og_title'    => $meta->ogTitle,
                    'og_description' => $meta->ogDescription,
                    'og_image'    => $meta->ogImage,
                    'twitter_title' => $meta->twitterTitle,
                    'twitter_description' => $meta->twitterDescription,
                    'twitter_image' => $meta->twitterImage,
                ]);
            },
            'args'                => [
                'post_id' => [
                    'type'     => 'integer',
                    'required' => true,
                ],
                'meta' => [
                    'type'     => 'object',
                    'required' => false,
                ],
            ],
        ]);
    }
}
