<?php

namespace Elementor_Pay_Addons\API;
use Elementor_Pay_Addons\Shared\Logger;
use Elementor_Pay_Addons\Core\Config_Service;

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

// Exit if accessed directly

use Elementor_Pay_Addons\Shared\Security_Utils;
use Elementor_Pay_Addons\Core\Config;

class Rest_API_Settings_Controller extends \WP_REST_Controller
{
    public function __construct()
    {
        $this->namespace = EPA_ADDONS_REST_API . 'admin';
        $this->rest_base = 'settings';
    }

    public function register_routes()
    {
        register_rest_route($this->namespace, $this->rest_base, array(
            array(
                'methods'            => \WP_REST_Server::READABLE,
                'callback'          => array($this, 'get_settings'),
                'permission_callback' => array($this, 'verify_admin')
            ),
            array(
                'methods'              => \WP_REST_Server::EDITABLE,
                'callback'            => array($this, 'update_settings'),
                'permission_callback' => array( $this, 'verify_admin' )
            )
        ));

        register_rest_route($this->namespace, $this->rest_base . '/elements', array(
            array(
                'methods'            => \WP_REST_Server::READABLE,
                'callback'          => array($this, 'get_elements'),
                'permission_callback' => array($this, 'verify_admin')
            ),
            array(
                'methods'              => \WP_REST_Server::EDITABLE,
                'callback'            => array($this, 'update_elements'),
                'permission_callback' => array($this, 'verify_admin')
            )
        ));

        register_rest_route($this->namespace, $this->rest_base . '/import-test', array(
            array(
                'methods'              => \WP_REST_Server::EDITABLE,
                'callback'            => array($this, 'import_test_settings'),
                'permission_callback' => array($this, 'verify_admin' )
            )
        ));

        register_rest_route($this->namespace, $this->rest_base . '/import-template', array(
            array(
                'methods'              => \WP_REST_Server::EDITABLE,
                'callback'            => array($this, 'import_template'),
                'permission_callback' => array($this, 'verify_admin' )
            )
        ));

        register_rest_route($this->namespace, $this->rest_base . '/download-log', array(
            array(
                'methods'             => \WP_REST_Server::READABLE,
                'callback'            => array($this, 'download_log'),
                'permission_callback' => array($this, 'verify_admin')
            )
        ));
    }

    function verify_admin(\WP_REST_Request $request)
    {
        return Security_Utils::admin_check($request);
    }

    /**
     * Retrieve settings.
     *
     * @return WP_REST_Response
     */
    public function get_settings()
    {
        $stripe_settings      = get_option('epa_stripe_settings', []);
        $sys_settings      = get_option('epa_sys_settings', []);
        return new \WP_REST_Response(
            [
                'test_mode' => $stripe_settings['test_mode'] ?? false,
                'test_publishable_key' => $stripe_settings['test_publishable_key'] ?? '',
                'live_publishable_key' => $stripe_settings['live_publishable_key'] ?? '',
                'test_secret_key' => ! empty( $stripe_settings['test_secret_key'] ) ? self::mask_key( $stripe_settings['test_secret_key'] ) : '',
                'live_secret_key' => ! empty( $stripe_settings['live_secret_key'] ) ? self::mask_key( $stripe_settings['live_secret_key'] ) : '',
                'webhook_secret' => ! empty( $stripe_settings['webhook_secret'] ) ? self::mask_key( $stripe_settings['webhook_secret'] ) : '',
                'test_webhook_secret' => ! empty( $stripe_settings['test_webhook_secret'] ) ? self::mask_key( $stripe_settings['test_webhook_secret'] ) : '',
                'default_currency' => $stripe_settings['default_currency'] ?? 'USD', 
                'enable_logging' => $sys_settings['enable_logging'] ?? false,
                'enable_keep_data' => $sys_settings['enable_keep_data'] ?? false,
            ]
        );
    }

    /**
     * Mask a secret key so it is not fully exposed in REST responses.
     *
     * @param string $key The secret key to mask.
     * @return string Masked key showing only the last 4 characters.
     */
    private static function mask_key( $key ) {
        if ( strlen( $key ) <= 11 ) {
            return substr( $key, 0, 3 ) . str_repeat( '*', max( 0, strlen( $key ) - 3 ) );
        }
        return substr( $key, 0, 7 ) . str_repeat( '*', strlen( $key ) - 11 ) . substr( $key, -4 );
    }

    /**
     * Update settings.
     *
     * @param WP_REST_Request $request Full data about the request.
     */
    public function update_settings(\WP_REST_Request $request)
    {
        $params = $request->get_params();
        
        $stripe_settings = get_option('epa_stripe_settings', []);
        $stripe_settings['test_mode'] = rest_sanitize_boolean( $params['test_mode'] ?? false );
        $stripe_settings['default_currency'] = sanitize_text_field( $params['default_currency'] ?? 'USD' );
        if ( isset( $params['test_publishable_key'] ) && ! self::is_masked( $params['test_publishable_key'] ) ) {
            $stripe_settings['test_publishable_key'] = sanitize_text_field( $params['test_publishable_key'] );
        }
        if ( isset( $params['live_publishable_key'] ) && ! self::is_masked( $params['live_publishable_key'] ) ) {
            $stripe_settings['live_publishable_key'] = sanitize_text_field( $params['live_publishable_key'] );
        }
        if ( isset( $params['test_secret_key'] ) && ! self::is_masked( $params['test_secret_key'] ) ) {
            $stripe_settings['test_secret_key'] = sanitize_text_field( $params['test_secret_key'] );
        }
        if ( isset( $params['live_secret_key'] ) && ! self::is_masked( $params['live_secret_key'] ) ) {
            $stripe_settings['live_secret_key'] = sanitize_text_field( $params['live_secret_key'] );
        }
        if ( isset( $params['webhook_secret'] ) && ! self::is_masked( $params['webhook_secret'] ) ) {
            $stripe_settings['webhook_secret'] = sanitize_text_field( $params['webhook_secret'] );
        }
        if ( isset( $params['test_webhook_secret'] ) && ! self::is_masked( $params['test_webhook_secret'] ) ) {
            $stripe_settings['test_webhook_secret'] = sanitize_text_field( $params['test_webhook_secret'] );
        }
        update_option('epa_stripe_settings', $stripe_settings);

        $sys_settings = get_option('epa_sys_settings', []);
        $sys_settings['enable_logging'] = rest_sanitize_boolean( $params['enable_logging'] ?? false );
        $sys_settings['enable_keep_data'] = rest_sanitize_boolean( $params['enable_keep_data'] ?? false );
        update_option('epa_sys_settings', $sys_settings);

        return new \WP_REST_Response( [ 'success' => true ], 200);
    }

    /**
     * Check if a value is a masked key (should not be saved).
     *
     * @param string $value
     * @return bool
     */
    private static function is_masked( $value ) {
        return strpos( $value, '***' ) !== false;
    }

    /**
     * import test setting.
     *
     * @param WP_REST_Request $request Full data about the request.
     */
    public function import_test_settings(\WP_REST_Request $request)
    {
        Logger::debug('import_test_settings');
        $config = Config_Service::get_test_config();
        
        $stripe_settings = get_option('epa_stripe_settings', []);
        $stripe_settings['test_publishable_key'] = $config['test_key'];
        $stripe_settings['test_secret_key'] = $config['test_secret'];
        $stripe_settings['default_currency'] = $config['currency'];
        $stripe_settings['test_mode'] = true;
        update_option('epa_stripe_settings', $stripe_settings);

        
        return new \WP_REST_Response($config, 200);
    }
    
    /**
     * import test setting.
     *
     * @param WP_REST_Request $request Full data about the request.
     */
    public function import_template(\WP_REST_Request $request)
    {
        Logger::debug('import_template');
        $params = $request->get_params();
        $url = isset( $params['url'] ) ? esc_url_raw( $params['url'] ) : '';

        if ( empty( $url ) ) {
            return new \WP_REST_Response(['error' => 'URL is required'], 400);
        }

        // Only allow downloads from the official Pay Addons template domains.
        $allowed_hosts = array(
            wp_parse_url( EPA_PLUGIN_TEMPLATE_URL, PHP_URL_HOST ),
            'data.payaddons.com',
        );
        $request_host = wp_parse_url( $url, PHP_URL_HOST );
        if ( ! in_array( $request_host, $allowed_hosts, true ) ) {
            return new \WP_REST_Response(['error' => 'Invalid template URL'], 403);
        }

        Config_Service::import_template($url);

        $templates_url = add_query_arg( array( 
            'post_type' => 'elementor_library', 
            'tabs_group' => 'library', 
        ), admin_url( 'edit.php' ) );
        
        return new \WP_REST_Response([
            'template_url' => $templates_url
        ], 200);
    }

    /**
     * Retrieve selected elements.
     *
     * @return WP_REST_Response
     */
    public function get_elements()
    {
        $elements = Config::get_all_elements();
        return new \WP_REST_Response($elements);
    }

    /**
     * Update elements.
     *
     * @param WP_REST_Request $request Full data about the request.
     */
    public function update_elements(\WP_REST_Request $request)
    {
        $params = $request->get_params();
        $elements = isset( $params['elements'] ) && is_array( $params['elements'] ) ? array_map( 'sanitize_text_field', $params['elements'] ) : [];
        Config::update_elements($elements);
        return new \WP_REST_Response( [ 'success' => true ], 200);
    }

    /**
     * Download latest log file.
     *
     * @return WP_REST_Response|void
     */
    public function download_log()
    {
        $log_file = Logger::getLogFile();

        if (!$log_file || !file_exists($log_file)) {
            return new \WP_REST_Response(['message' => 'No log file found.'], 404);
        }

        // Ensure log file is within expected directory to prevent path traversal.
        $real_log_file = realpath( $log_file );
        $real_log_dir  = realpath( EPA_ADDONS_LOG_FOLDER );
        if ( false === $real_log_file || false === $real_log_dir || 0 !== strpos( $real_log_file, $real_log_dir ) ) {
            return new \WP_REST_Response(['message' => 'Invalid log file path.'], 403);
        }

        $filename = basename($log_file);
        $filename = preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename);
        header('Content-Type: text/plain');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: ' . filesize($real_log_file));
        readfile($real_log_file); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile
        exit;
    }
}
