<?php

namespace WPDeveloper\BetterDocsPro\REST;

use WP_REST_Request;
use WP_REST_Server;
use WPDeveloper\BetterDocs\Core\BaseAPI;
use WPDeveloper\BetterDocs\Core\Settings;
use WPDeveloper\BetterDocs\Dependencies\DI\Container;
use WPDeveloper\BetterDocsPro\Core\RelatedDocsEngine;

class RelatedDocs extends BaseAPI {

    /**
     * RelatedDocsEngine instance
     *
     * @var RelatedDocsEngine
     */
    private $engine;

    public function __construct( Settings $settings, Container $container ) {
        parent::__construct( $settings, $container );
        $this->engine = $container->get( RelatedDocsEngine::class );
    }

    public function register() {
        // Public route — frontend feature, no auth required.
        register_rest_route( $this->get_namespace(), 'get-related-docs', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ $this, 'get_related_docs' ],
            'permission_callback' => '__return_true',
        ] );

        // Editor route — read the persisted (already-generated) suggestion
        // cache for an article. No engine run, no OpenAI call.
        register_rest_route( $this->get_namespace(), 'saved-related-docs', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ $this, 'get_saved_related_docs' ],
            'permission_callback' => function ( WP_REST_Request $request ) {
                return $this->can_edit_article( $request->get_param( 'article_id' ) );
            },
        ] );

        // Editor route — run the engine, persist, and return the suggestions.
        // This is the only path that may trigger an OpenAI call from the
        // editor, and only on an explicit "Generate"/"Regenerate" click.
        register_rest_route( $this->get_namespace(), 'generate-related-docs', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ $this, 'generate_related_docs' ],
            'permission_callback' => function ( WP_REST_Request $request ) {
                return $this->can_edit_article( $request->get_param( 'article_id' ) );
            },
        ] );

        // Admin-only route — analytics dashboard.
        register_rest_route( $this->get_namespace(), 'related-docs-analytics', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ $this, 'get_analytics' ],
            'permission_callback' => function () {
                return current_user_can( 'manage_options' );
            },
        ] );
    }

    /**
     * Capability gate for the editor suggestion routes.
     *
     * The author must be able to edit the specific docs post. A separate
     * route per permission tier — never branch authorization on the request
     * URI.
     */
    private function can_edit_article( $article_id ) {
        $article_id = (int) $article_id;

        if ( ! $article_id ) {
            return false;
        }

        return current_user_can( 'edit_post', $article_id );
    }

    /**
     * Get related docs for an article
     */
    public function get_related_docs( WP_REST_Request $request ) {
        $article_id = $request->get_param( 'article_id' );

        if ( empty( $article_id ) ) {
            return $this->error( 'missing_article_id', 'Article ID is required', 400 );
        }

        // Validate that the article exists and is a docs post
        $post = get_post( $article_id );
        if ( ! $post || $post->post_type !== 'docs' ) {
            return $this->error( 'invalid_article', 'Invalid article ID or not a docs post', 400 );
        }

        try {
            // Call the engine method directly with the request
            return $this->engine->get_related_docs( $request );

        } catch ( \Exception $e ) {
            return $this->error( 'exception', 'Error getting related docs: ' . $e->getMessage(), 500 );
        }
    }

    /**
     * Return the persisted suggestion cache for the editor metabox.
     *
     * Never runs the engine — the metabox stays empty (showing its
     * "Generate" CTA) until the author explicitly generates.
     */
    public function get_saved_related_docs( WP_REST_Request $request ) {
        $article_id = (int) $request->get_param( 'article_id' );

        $post = get_post( $article_id );
        if ( ! $post || $post->post_type !== 'docs' ) {
            return $this->error( 'invalid_article', 'Invalid article ID or not a docs post', 400 );
        }

        try {
            return rest_ensure_response( [
                'success' => true,
                'data'    => $this->engine->get_persisted_suggestions( $article_id ),
            ] );
        } catch ( \Exception $e ) {
            return $this->error( 'exception', 'Error reading saved related docs: ' . $e->getMessage(), 500 );
        }
    }

    /**
     * Generate (or regenerate) suggestions for the editor and persist them.
     */
    public function generate_related_docs( WP_REST_Request $request ) {
        $article_id = (int) $request->get_param( 'article_id' );

        $post = get_post( $article_id );
        if ( ! $post || $post->post_type !== 'docs' ) {
            return $this->error( 'invalid_article', 'Invalid article ID or not a docs post', 400 );
        }

        // Editor generation requires an OpenAI key. Without one the engine would
        // silently fall back to content/collaborative-only results, which is
        // misleading in the metabox — the author asked for *AI* suggestions.
        // The public get-related-docs path intentionally still degrades (rule #8);
        // this gate is editor-only. The JS surfaces the `no_api_key` code as the
        // "Configuration Required" card.
        if ( empty( $this->settings->get( 'ai_autowrite_api_key', '' ) ) ) {
            return $this->error( 'no_api_key', 'OpenAI API key is not configured.', 400 );
        }

        $limit = (int) $request->get_param( 'limit' );

        try {
            return rest_ensure_response( [
                'success' => true,
                'data'    => $this->engine->generate_and_persist_suggestions( $article_id, $limit ),
            ] );
        } catch ( \Exception $e ) {
            return $this->error( 'exception', 'Error generating related docs: ' . $e->getMessage(), 500 );
        }
    }

    /**
     * Get analytics data for related docs
     */
    public function get_analytics( WP_REST_Request $request ) {
        try {
            // Call the engine method directly with the request
            return $this->engine->get_analytics( $request );

        } catch ( \Exception $e ) {
            return $this->error( 'exception', 'Error getting analytics: ' . $e->getMessage(), 500 );
        }
    }
}
