<?php

declare(strict_types=1);

namespace ProRank\SEO\Core\RestApi;

use ProRank\SEO\Core\Content\TitleAuditor;
use ProRank\SEO\Core\Content\TitleRewriter;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
use WP_Error;

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

/**
 * Title-too-long surface.
 *
 *  - scan / post / suggest / repair-all preview = READ ONLY.
 *  - apply / restore write ONLY the _prorank_seo_title meta, one post at a
 *    time, and require BOTH the ProRank edit-meta capability AND core
 *    edit_post on that specific post. Every write defaults to a dry run.
 *  - There is no bulk commit in P0 (repair-all is preview only).
 */
class TitlesController extends BaseController {

    protected $rest_base = 'titles';

    /** Read-only rendered verification can cover a larger set than a write. */
    private const VERIFY_MAX = 500;

    /**
     * Per-post write guard: ProRank edit-meta capability AND core edit_post
     * on that exact post (a title rewrite edits real published content).
     */
    public function check_apply_single( WP_REST_Request $request ): bool {
        $post_id = (int) $request['id'];
        return $this->check_edit_meta() && $post_id > 0 && current_user_can( 'edit_post', $post_id );
    }

    public function register_routes(): void {
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/scan',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [ $this, 'scan' ],
                    'permission_callback' => [ $this, 'check_run_audits' ],
                    'args'                => [
                        'verify' => [
                            'default'           => false,
                            'sanitize_callback' => 'rest_sanitize_boolean',
                        ],
                        'limit' => [
                            'default'           => self::VERIFY_MAX,
                            'sanitize_callback' => 'absint',
                        ],
                    ],
                ],
            ]
        );

        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/post/(?P<id>\d+)',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [ $this, 'get_post_diagnosis' ],
                    'permission_callback' => [ $this, 'check_run_audits' ],
                    'args'                => [
                        'id' => [
                            'required'          => true,
                            'sanitize_callback' => 'absint',
                        ],
                    ],
                ],
            ]
        );

        // Deterministic suggestion — READ ONLY (never writes).
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/suggest/(?P<id>\d+)',
            [
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [ $this, 'suggest' ],
                    'permission_callback' => [ $this, 'check_run_audits' ],
                    'args'                => [
                        'id' => [ 'required' => true, 'sanitize_callback' => 'absint' ],
                    ],
                ],
            ]
        );

        // Explicit per-title apply — writes ONLY _prorank_seo_title.
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/apply/(?P<id>\d+)',
            [
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [ $this, 'apply' ],
                    'permission_callback' => [ $this, 'check_apply_single' ],
                    'args'                => [
                        'id'      => [ 'required' => true, 'sanitize_callback' => 'absint' ],
                        'title'   => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ],
                        'dry_run' => [ 'default' => true, 'sanitize_callback' => 'rest_sanitize_boolean' ],
                    ],
                ],
            ]
        );

        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/restore/(?P<id>\d+)',
            [
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [ $this, 'restore' ],
                    'permission_callback' => [ $this, 'check_apply_single' ],
                    'args'                => [
                        'id'      => [ 'required' => true, 'sanitize_callback' => 'absint' ],
                        'dry_run' => [ 'default' => true, 'sanitize_callback' => 'rest_sanitize_boolean' ],
                    ],
                ],
            ]
        );

        // P0 repair-all is PREVIEW ONLY — never writes regardless of input.
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/repair-all',
            [
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [ $this, 'repair_all_preview' ],
                    'permission_callback' => [ $this, 'check_run_audits' ],
                    'args'                => [
                        'limit' => [ 'default' => 200, 'sanitize_callback' => 'absint' ],
                    ],
                ],
            ]
        );
    }

    public function suggest( WP_REST_Request $request ) {
        $post_id = (int) $request['id'];
        if ( ! get_post( $post_id ) ) {
            return new WP_Error( 'prorank_title_not_found', __( 'Post not found.', 'prorank-seo' ), [ 'status' => 404 ] );
        }
        return new WP_REST_Response( ( new TitleRewriter() )->suggest( $post_id ), 200 );
    }

    public function apply( WP_REST_Request $request ) {
        $post_id = (int) $request['id'];
        if ( ! get_post( $post_id ) ) {
            return new WP_Error( 'prorank_title_not_found', __( 'Post not found.', 'prorank-seo' ), [ 'status' => 404 ] );
        }
        $dry_run = (bool) $request['dry_run'];
        $res = ( new TitleRewriter() )->apply( $post_id, (string) $request['title'], $dry_run );
        return new WP_REST_Response( $res, 200 );
    }

    public function restore( WP_REST_Request $request ) {
        $post_id = (int) $request['id'];
        if ( ! get_post( $post_id ) ) {
            return new WP_Error( 'prorank_title_not_found', __( 'Post not found.', 'prorank-seo' ), [ 'status' => 404 ] );
        }
        $dry_run = (bool) $request['dry_run'];
        $res = ( new TitleRewriter() )->restore( $post_id, $dry_run );
        if ( ( $res['reason'] ?? '' ) === 'no_backup' ) {
            return new WP_Error( 'prorank_title_no_backup', __( 'No restorable backup exists for this post.', 'prorank-seo' ), [ 'status' => 404 ] );
        }
        return new WP_REST_Response( $res, 200 );
    }

    public function repair_all_preview( WP_REST_Request $request ): WP_REST_Response {
        $limit = max( 1, min( 500, (int) $request['limit'] ) );
        return new WP_REST_Response( ( new TitleRewriter() )->repair_all_preview( $limit ), 200 );
    }

    public function scan( WP_REST_Request $request ): WP_REST_Response {
        $auditor = new TitleAuditor();
        if ( (bool) $request['verify'] ) {
            $limit = max( 1, min( self::VERIFY_MAX, (int) $request['limit'] ) );
            return new WP_REST_Response( $auditor->verify( $limit ), 200 );
        }
        return new WP_REST_Response( $auditor->scan(), 200 );
    }

    public function get_post_diagnosis( WP_REST_Request $request ) {
        $post_id = (int) $request['id'];
        if ( ! get_post( $post_id ) ) {
            return new WP_Error( 'prorank_title_not_found', __( 'Post not found.', 'prorank-seo' ), [ 'status' => 404 ] );
        }
        $auditor = new TitleAuditor();
        return new WP_REST_Response(
            [
                'post_id'   => $post_id,
                'permalink' => get_permalink( $post_id ),
                'edit_link' => admin_url( 'post.php?post=' . $post_id . '&action=edit' ),
                'diagnosis' => $auditor->diagnose_post( $post_id ),
                'rendered'  => $auditor->verify_rendered( $post_id ),
            ],
            200
        );
    }
}
