<?php
declare(strict_types=1);

namespace KbMarkdownImporter;

use KbMarkdownImporter\Admin\SettingsPage;
use KbMarkdownImporter\Admin\ProductsPage;
use KbMarkdownImporter\Admin\StatusPage;
use KbMarkdownImporter\Admin\SyncPage;
use KbMarkdownImporter\Frontend\Router;
use KbMarkdownImporter\Frontend\SearchController;
use KbMarkdownImporter\Import\ImportManager;

final class Plugin
{
    private static ?self $instance = null;

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

        return self::$instance;
    }

    public function boot(): void
    {
        add_action('init', [$this, 'registerContentTypes']);
        add_action('init', [$this, 'registerShortcodes']);
        add_action('admin_menu', [$this, 'registerAdminPages']);
        add_action('admin_init', [SettingsPage::class, 'registerSettings']);
        add_action('admin_enqueue_scripts', [$this, 'enqueueAdminAssets']);
        add_action('rest_api_init', [$this, 'registerRestRoutes']);
        add_filter('cron_schedules', [$this, 'addCronSchedules']);
        add_filter('upload_mimes', [$this, 'allowCssUploads']);
        add_action('kb_markdown_importer_cron_sync', [$this, 'runCronSync']);
        add_action('wp_enqueue_scripts', [$this, 'enqueueFrontendAssets']);

        (new Router())->boot();
    }

    public static function activate(): void
    {
        self::instance()->registerContentTypes();
        (new Router())->addRewriteRules();
        self::grantCapabilities();
        self::ensureDefaultSettings();
        flush_rewrite_rules();
    }

    public static function deactivate(): void
    {
        wp_clear_scheduled_hook('kb_markdown_importer_cron_sync');
        flush_rewrite_rules();
    }

    public function registerContentTypes(): void
    {
        register_post_type('kb_doc_page', [
            'labels' => [
                'name' => __('Documentation Pages', 'kb-markdown-importer'),
                'singular_name' => __('Documentation Page', 'kb-markdown-importer'),
            ],
            'public' => false,
            'show_ui' => true,
            'show_in_menu' => 'kb-markdown-importer',
            'show_in_rest' => true,
            'supports' => ['title', 'editor', 'excerpt', 'custom-fields'],
            'capability_type' => 'post',
        ]);

        register_taxonomy('kb_product', ['kb_doc_page'], [
            'labels' => [
                'name' => __('Products', 'kb-markdown-importer'),
                'singular_name' => __('Product', 'kb-markdown-importer'),
            ],
            'public' => false,
            'show_ui' => true,
            'show_in_rest' => true,
            'hierarchical' => false,
            'rewrite' => false,
        ]);

        register_taxonomy('kb_version', ['kb_doc_page'], [
            'labels' => [
                'name' => __('Versions', 'kb-markdown-importer'),
                'singular_name' => __('Version', 'kb-markdown-importer'),
            ],
            'public' => false,
            'show_ui' => true,
            'show_in_rest' => true,
            'hierarchical' => false,
            'rewrite' => false,
        ]);

        register_taxonomy('kb_component', ['kb_doc_page'], [
            'labels' => [
                'name' => __('Components', 'kb-markdown-importer'),
                'singular_name' => __('Component', 'kb-markdown-importer'),
            ],
            'public' => false,
            'show_ui' => true,
            'show_in_rest' => true,
            'hierarchical' => false,
            'rewrite' => false,
        ]);
    }

    public function registerAdminPages(): void
    {
        add_menu_page(
            __('Knowledgebase', 'kb-markdown-importer'),
            __('Knowledgebase', 'kb-markdown-importer'),
            'manage_kb_docs',
            'kb-markdown-importer',
            [StatusPage::class, 'render'],
            'dashicons-welcome-learn-more',
            58
        );

        add_submenu_page('kb-markdown-importer', __('Overview', 'kb-markdown-importer'), __('Overview', 'kb-markdown-importer'), 'manage_kb_docs', 'kb-markdown-importer', [StatusPage::class, 'render']);
        add_submenu_page('kb-markdown-importer', __('Products', 'kb-markdown-importer'), __('Products', 'kb-markdown-importer'), 'manage_kb_docs', 'kb-markdown-products', [ProductsPage::class, 'render']);
        add_submenu_page('kb-markdown-importer', __('Synchronization', 'kb-markdown-importer'), __('Synchronization', 'kb-markdown-importer'), 'sync_kb_docs', 'kb-markdown-sync', [SyncPage::class, 'render']);
        add_submenu_page('kb-markdown-importer', __('Settings', 'kb-markdown-importer'), __('Settings', 'kb-markdown-importer'), 'manage_kb_docs', 'kb-markdown-settings', [SettingsPage::class, 'render']);
    }

    public function registerRestRoutes(): void
    {
        register_rest_route('kb-markdown/v1', '/status', [
            'methods' => 'GET',
            'callback' => [StatusPage::class, 'restStatus'],
            'permission_callback' => static fn (): bool => current_user_can('manage_kb_docs'),
        ]);

        register_rest_route('kb-markdown/v1', '/sync', [
            'methods' => 'POST',
            'callback' => static fn (\WP_REST_Request $request): \WP_REST_Response => (new ImportManager())->syncAll((bool) $request->get_param('dry_run')),
            'permission_callback' => static fn (): bool => current_user_can('sync_kb_docs'),
        ]);

        register_rest_route('kb-markdown/v1', '/sync/project', [
            'methods' => 'POST',
            'callback' => static fn (\WP_REST_Request $request): \WP_REST_Response => (new ImportManager())->syncProject((string) $request->get_param('project_id'), (bool) $request->get_param('dry_run')),
            'permission_callback' => static fn (): bool => current_user_can('sync_kb_docs'),
        ]);

        register_rest_route('kb-markdown/v1', '/search', [
            'methods' => 'GET',
            'callback' => [SearchController::class, 'restSearch'],
            'permission_callback' => '__return_true',
        ]);

        register_rest_route('kb-markdown/v1', '/gitlab-webhook', [
            'methods' => 'POST',
            'callback' => static fn (): \WP_REST_Response => new \WP_REST_Response(['queued' => false, 'message' => 'Webhook endpoint is reserved for a later event-driven sync implementation.']),
            'permission_callback' => static fn (): bool => current_user_can('sync_kb_docs'),
        ]);
    }

    public function registerShortcodes(): void
    {
        add_shortcode('kb_docs_index', [Router::class, 'shortcodeDocsIndex']);
        add_shortcode('kb_docs', [Router::class, 'shortcodeDocsApp']);
        add_shortcode('kb_product_index', [Router::class, 'shortcodeProductIndex']);
        add_shortcode('kb_search', [SearchController::class, 'shortcodeSearch']);
    }

    public function addCronSchedules(array $schedules): array
    {
        $schedules['kb_markdown_weekly'] = [
            'interval' => WEEK_IN_SECONDS,
            'display' => __('Weekly', 'kb-markdown-importer'),
        ];

        return $schedules;
    }

    public function runCronSync(): void
    {
        (new ImportManager())->syncAll(false);
    }

    public function enqueueFrontendAssets(): void
    {
        $settings = self::settings();
        wp_enqueue_style('kb-markdown-frontend', KB_MARKDOWN_IMPORTER_URL . 'assets/css/frontend.css', [], KB_MARKDOWN_IMPORTER_VERSION);
        $designHandle = 'kb-markdown-frontend';

        if ('obyte' === $settings['design_theme']) {
            wp_enqueue_style('kb-markdown-theme-obyte', KB_MARKDOWN_IMPORTER_URL . 'assets/css/themes/obyte.css', ['kb-markdown-frontend'], KB_MARKDOWN_IMPORTER_VERSION);
            $designHandle = 'kb-markdown-theme-obyte';
        }

        if (! empty($settings['custom_theme_css_url'])) {
            wp_enqueue_style('kb-markdown-custom-theme', esc_url_raw((string) $settings['custom_theme_css_url']), [$designHandle], KB_MARKDOWN_IMPORTER_VERSION);
            $designHandle = 'kb-markdown-custom-theme';
        }

        $inlineCss = sprintf(
            '.kb-docs-wrap{--kb-accent:%1$s;--kb-radius:%2$dpx;} .kb-docs-wrap{--kb-primary:%1$s;--kb-ob-accent:%3$s;}',
            esc_html((string) $settings['design_primary_color']),
            max(0, min(32, (int) $settings['design_radius'])),
            esc_html((string) $settings['design_accent_color'])
        );
        wp_add_inline_style($designHandle, $inlineCss);
        wp_enqueue_script('kb-markdown-frontend', KB_MARKDOWN_IMPORTER_URL . 'assets/js/frontend.js', [], KB_MARKDOWN_IMPORTER_VERSION, true);
    }

    public function enqueueAdminAssets(string $hook): void
    {
        if (! str_contains($hook, 'kb-markdown-settings')) {
            return;
        }

        wp_enqueue_media();
        wp_enqueue_script('kb-markdown-admin-settings', KB_MARKDOWN_IMPORTER_URL . 'assets/js/admin-settings.js', ['jquery'], KB_MARKDOWN_IMPORTER_VERSION, true);
    }

    public function allowCssUploads(array $mimes): array
    {
        if (current_user_can('manage_kb_docs')) {
            $mimes['css'] = 'text/css';
        }

        return $mimes;
    }

    public static function settings(): array
    {
        return wp_parse_args((array) get_option('kb_markdown_importer_settings', []), Settings::defaults());
    }

    public static function syncCronSchedule(?array $settings = null): void
    {
        $settings = $settings ?: self::settings();
        wp_clear_scheduled_hook('kb_markdown_importer_cron_sync');

        if ('disabled' === $settings['cron_interval']) {
            return;
        }

        $schedule = match ($settings['cron_interval']) {
            'hourly' => 'hourly',
            'daily' => 'daily',
            'weekly' => 'kb_markdown_weekly',
            default => '',
        };

        if ($schedule && ! wp_next_scheduled('kb_markdown_importer_cron_sync')) {
            wp_schedule_event(time() + HOUR_IN_SECONDS, $schedule, 'kb_markdown_importer_cron_sync');
        }
    }

    private static function ensureDefaultSettings(): void
    {
        if (false === get_option('kb_markdown_importer_settings', false)) {
            add_option('kb_markdown_importer_settings', Settings::defaults(), '', false);
        }
    }

    private static function grantCapabilities(): void
    {
        $role = get_role('administrator');

        if (! $role) {
            return;
        }

        foreach (['manage_kb_docs', 'view_kb_docs', 'sync_kb_docs'] as $capability) {
            $role->add_cap($capability);
        }
    }
}
