<?php
/**
 * System status and tools REST controller.
 *
 * @package RewindBrevoFormBridge
 */

namespace RewindBrevoFormBridge\Rest\Controllers;

use RewindBrevoFormBridge\Adapters\Registry;
use RewindBrevoFormBridge\Admin\Settings;
use RewindBrevoFormBridge\Feeds\Repository;
use RewindBrevoFormBridge\Logs\LogRepository;
use RewindBrevoFormBridge\Rest\BaseController;

defined( 'ABSPATH' ) || exit;

/**
 * Powers the Settings → Tools tab: a status report, and settings
 * export/import as JSON.
 *
 * The exported JSON never contains the API key — an export is a support
 * artefact and a portable configuration, not a credential backup.
 *
 * @since 0.4.0
 */
class SystemController extends BaseController {

	/**
	 * Settings storage service.
	 *
	 * @var Settings
	 */
	private Settings $settings;

	/**
	 * Feed repository.
	 *
	 * @var Repository
	 */
	private Repository $feeds;

	/**
	 * Log repository.
	 *
	 * @var LogRepository
	 */
	private LogRepository $logs;

	/**
	 * Adapter registry.
	 *
	 * @var Registry
	 */
	private Registry $registry;

	/**
	 * Constructor.
	 *
	 * @since 0.4.0
	 * @param Settings      $settings Settings storage service.
	 * @param Repository    $feeds    Feed repository.
	 * @param LogRepository $logs     Log repository.
	 * @param Registry      $registry Adapter registry.
	 */
	public function __construct( Settings $settings, Repository $feeds, LogRepository $logs, Registry $registry ) {
		parent::__construct( 'system' );

		$this->settings = $settings;
		$this->feeds    = $feeds;
		$this->logs     = $logs;
		$this->registry = $registry;
	}

	/**
	 * Register routes.
	 *
	 * @since 0.4.0
	 * @return void
	 */
	public function register_routes(): void {
		register_rest_route(
			self::NAMESPACE_V1,
			'/' . $this->rest_base . '/status',
			array(
				'methods'             => \WP_REST_Server::READABLE,
				'callback'            => array( $this, 'status' ),
				'permission_callback' => array( $this, 'can_manage' ),
			)
		);

		register_rest_route(
			self::NAMESPACE_V1,
			'/' . $this->rest_base . '/export',
			array(
				'methods'             => \WP_REST_Server::READABLE,
				'callback'            => array( $this, 'export' ),
				'permission_callback' => array( $this, 'can_manage' ),
			)
		);

		register_rest_route(
			self::NAMESPACE_V1,
			'/' . $this->rest_base . '/import',
			array(
				'methods'             => \WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'import' ),
				'permission_callback' => array( $this, 'can_manage' ),
				'args'                => array(
					'settings' => array(
						'type'     => 'object',
						'required' => true,
					),
				),
			)
		);
	}

	/**
	 * The system status report.
	 *
	 * @since 0.4.0
	 * @return \WP_REST_Response
	 */
	public function status(): \WP_REST_Response {
		global $wpdb, $wp_version;

		$adapters = array();
		foreach ( $this->registry->available() as $adapter ) {
			$adapters[] = $adapter->label();
		}

		$tables = array();
		foreach ( array( 'rbfb_feeds', 'rbfb_log', 'rbfb_consent' ) as $suffix ) {
			$table            = $wpdb->prefix . $suffix;
			// A live schema check for the status report; a cached answer would
			// defeat the point of asking.
			$tables[ $suffix ] = (bool) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		}

		$failure = $this->logs->last_failure();

		return $this->respond(
			array(
				'environment' => array(
					'php'            => PHP_VERSION,
					'wordpress'      => (string) $wp_version,
					'plugin'         => RBFB_VERSION,
					'db_version'     => (string) get_option( 'rbfb_db_version', '' ),
					'mysql'          => (string) $wpdb->db_version(),
					'ssl'            => is_ssl(),
					'wp_cron'        => ! ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ),
					'memory_limit'   => (string) ini_get( 'memory_limit' ),
					'timezone'       => (string) wp_timezone_string(),
				),
				'tables'      => $tables,
				'data'        => array(
					'feeds' => $this->feeds->count(),
					'logs'  => $this->logs->count(),
				),
				'connection'  => array(
					'has_key'       => '' !== $this->settings->api_key(),
					'key_source'    => $this->settings->api_key_source(),
					'last_verified' => (string) get_option( 'rbfb_last_verified', '' ),
					'cached_at'     => (string) get_option( 'rbfb_cache_stamp', '' ),
				),
				'adapters'    => $adapters,
				'last_error'  => null === $failure ? null : array(
					'created_at' => $failure['created_at'],
					'message'    => $failure['message'],
					'error_code' => $failure['error_code'],
					'http_code'  => $failure['http_code'],
				),
			)
		);
	}

	/**
	 * Export settings as a portable structure, minus the API key.
	 *
	 * @since 0.4.0
	 * @return \WP_REST_Response
	 */
	public function export(): \WP_REST_Response {
		$settings = $this->settings->all();

		unset( $settings['api_key'], $settings['api_key_source'] );

		return $this->respond(
			array(
				'exported_at' => current_time( 'mysql', true ),
				'plugin'      => RBFB_VERSION,
				'settings'    => $settings,
				'filename'    => 'rbfb-settings-' . gmdate( 'Y-m-d' ) . '.json',
			)
		);
	}

	/**
	 * Import a settings structure through the normal sanitizer.
	 *
	 * @since 0.4.0
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function import( \WP_REST_Request $request ) {
		$incoming = $request->get_param( 'settings' );

		if ( ! is_array( $incoming ) ) {
			return $this->error( 'rbfb_bad_import', __( 'That file did not contain a settings object.', 'rewind-form-bridge-for-brevo' ) );
		}

		// An import must never be able to set or clear the key.
		unset( $incoming['api_key'], $incoming['api_key_source'] );

		$merged  = wp_parse_args( $incoming, $this->settings->all() );
		$cleaned = $this->settings->sanitize( $merged );

		update_option( Settings::OPTION, $cleaned, false );

		return $this->respond( array( 'imported' => true ) );
	}
}
