<?php
declare(strict_types=1);


namespace ProRank\SEO\Core\RestApi;

use ProRank\SEO\Core\ServiceContainer;
use WP_REST_Controller;

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




abstract class BaseController extends WP_REST_Controller {
    protected $container;
    protected $namespace = 'prorank-seo/v1';
    
    public function __construct(ServiceContainer $container = null) {
        if ($container) {
            $this->container = $container;
        } else if (function_exists('prorank')) {
            // Fallback to global container if not injected
            $this->container = prorank()->get_container();
        }
        
        // Add CORS support
        add_action('rest_api_init', [$this, 'add_cors_headers'], 15);
    }
    
    // Child classes must implement register_routes() method from WP_REST_Controller
    
    /**
     * Add CORS headers for REST API requests
     */
    public function add_cors_headers() {
        // Remove existing CORS headers if any
        remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
        
        // Add our custom CORS headers
        add_filter('rest_pre_serve_request', function($value) {
            $origin = get_http_origin();
            
            if ($origin && $this->is_allowed_origin($origin)) {
                header('Access-Control-Allow-Origin: ' . $origin);
                header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
                header('Access-Control-Allow-Headers: Content-Type, Authorization, X-WP-Nonce, X-ProRank-API-Key');
                header('Access-Control-Allow-Credentials: true');
                header('Vary: Origin');
            }
            
            return $value;
        });
        
        // Handle preflight requests (guard for CLI/cron where REQUEST_METHOD is absent)
        $request_method = function_exists( 'prorank_get_server_var' )
            ? strtoupper( prorank_get_server_var( 'REQUEST_METHOD' ) )
            : '';
        if ('OPTIONS' === $request_method) {
            status_header(200);
            exit();
        }
    }
    
    /**
     * Check if the origin is allowed
     * 
     * @param string $origin
     * @return bool
     */
    private function is_allowed_origin($origin) {
        if (!is_string($origin) || $origin === '') {
            return false;
        }

        $parsed_origin = wp_parse_url($origin);
        $parsed_home = wp_parse_url(home_url());

        $origin_host = $parsed_origin['host'] ?? '';
        $home_host = $parsed_home['host'] ?? '';
        
        // Allow same domain (even with different ports in development)
        if (!empty($origin_host) && !empty($home_host) && strtolower($origin_host) === strtolower($home_host)) {
            return true;
        }
        
        // Add any other allowed origins here
        $allowed_origins = apply_filters('prorank_allowed_cors_origins', []);
        
        return in_array($origin, $allowed_origins, true);
    }
    
    public function check_admin_permission() {
        // Handle OPTIONS requests for CORS preflight
        $request_method = function_exists( 'prorank_get_server_var' )
            ? strtoupper( prorank_get_server_var( 'REQUEST_METHOD' ) )
            : '';
        if ($request_method === 'OPTIONS') {
            return true;
        }
        
        return current_user_can('manage_options');
    }
    
    /**
     * Alias for check_admin_permission for backward compatibility
     *
     * @return bool
     */
    public function check_permission() {
        return $this->check_admin_permission();
    }
    
    protected function success($data = null) {
        return rest_ensure_response([
            'success' => true,
            'data' => $data
        ]);
    }
    
    protected function error($message, $code = 'error', $status = 400) {
        return new \WP_Error($code, $message, ['status' => $status]);
    }

    /**
     * Backward-compatible success response helper.
     *
     * @param mixed  $data    Response data
     * @param string $message Optional message
     * @return \WP_REST_Response
     */
    protected function success_response($data = null, string $message = ''): \WP_REST_Response {
        return $this->get_success_response($data, $message);
    }

    /**
     * Backward-compatible error response helper.
     *
     * @param string $message Error message
     * @param string $code    Error code
     * @param int    $status  HTTP status
     * @return \WP_Error
     */
    protected function error_response(string $message, string $code = 'error', int $status = 400): \WP_Error {
        return $this->get_error_response($message, $status, $code);
    }
    
    /**
     * Check permission to edit posts
     *
     * @return bool
     */
    public function check_permission_edit_posts() {
        return current_user_can('edit_posts');
    }
    
    /**
     * Get error response
     *
     * @param string $message Error message
     * @param int    $status  HTTP status code
     * @param string $code    Error code
     * @return \WP_Error
     */
    protected function get_error_response(string $message, int $status = 400, string $code = 'error'): \WP_Error {
        return new \WP_Error($code, $message, ['status' => $status]);
    }
    
    /**
     * Get success response
     *
     * @param mixed  $data    Response data
     * @param string $message Success message
     * @return \WP_REST_Response
     */
    protected function get_success_response($data = null, string $message = ''): \WP_REST_Response {
        $response = [
            'success' => true,
            'data' => $data
        ];
        
        if (!empty($message)) {
            $response['message'] = $message;
        }
        
        return rest_ensure_response($response);
    }
    
    /**
     * Try callback with error handling
     *
     * @param callable $callback Callback to execute
     * @return mixed
     */
    protected function try_callback(callable $callback) {
        try {
            return $callback();
        } catch (\Throwable $e) {
            prorank_log('[ProRank SEO] REST error: ' . $e->getMessage());
            return $this->get_error_response(
                __('Internal server error.', 'prorank-seo'),
                500,
                'internal_error'
            );
        }
    }
}
