<?php

declare(strict_types=1);

namespace SiteFort\Modules\Multisite;

use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;

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

/**
 * REST API endpoints for multisite settings and propagation actions.
 */
class MultisiteApi {

	public function register_routes(): void {
		if ( ! is_multisite() ) {
			return;
		}

		register_rest_route( 'sitefort/v1', '/multisite/sites', [
			'methods'             => WP_REST_Server::READABLE,
			'callback'            => [ $this, 'handle_list_sites' ],
			'permission_callback' => [ $this, 'check_permission' ],
		] );

		register_rest_route( 'sitefort/v1', '/multisite/settings', [
			[
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => [ $this, 'handle_get_settings' ],
				'permission_callback' => [ $this, 'check_permission' ],
			],
			[
				'methods'             => WP_REST_Server::EDITABLE,
				'callback'            => [ $this, 'handle_save_settings' ],
				'permission_callback' => [ $this, 'check_permission' ],
				'args'                => [
					'enforce_firewall'  => [
						'type'              => 'boolean',
						'sanitize_callback' => 'rest_sanitize_boolean',
						'default'           => false,
					],
					'enforce_hardening' => [
						'type'              => 'boolean',
						'sanitize_callback' => 'rest_sanitize_boolean',
						'default'           => false,
					],
					'network_lockout'   => [
						'type'              => 'boolean',
						'sanitize_callback' => 'rest_sanitize_boolean',
						'default'           => false,
					],
				],
			],
		] );

		register_rest_route( 'sitefort/v1', '/multisite/propagate', [
			[
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => [ $this, 'handle_propagate' ],
				'permission_callback' => [ $this, 'check_permission' ],
				'args'                => [
					'module' => [
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_key',
						'default'           => 'all',
					],
				],
			],
		] );
	}

	public function check_permission(): bool {
		return current_user_can( 'manage_network_options' );
	}

	public function handle_list_sites( WP_REST_Request $request ): WP_REST_Response {
		return new WP_REST_Response( NetworkSettingsService::list_sites( 100 ), 200 );
	}

	public function handle_get_settings( WP_REST_Request $request ): WP_REST_Response {
		return new WP_REST_Response( NetworkSettingsService::get_settings(), 200 );
	}

	public function handle_save_settings( WP_REST_Request $request ): WP_REST_Response {
		$updated = NetworkSettingsService::save_settings( [
			'enforce_firewall'  => $request->get_param( 'enforce_firewall' ),
			'enforce_hardening' => $request->get_param( 'enforce_hardening' ),
			'network_lockout'   => $request->get_param( 'network_lockout' ),
		] );
		$message = $updated
			? 'Network settings saved.'
			: 'Settings are already up to date.';

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

	public function handle_propagate( WP_REST_Request $request ): WP_REST_Response {
		$result = NetworkSettingsService::propagate( (string) $request->get_param( 'module' ) );
		if ( is_wp_error( $result ) ) {
			$status = (int) ( $result->get_error_data()['status'] ?? 400 );
			return new WP_REST_Response(
				[
					'success' => false,
					'message' => $result->get_error_message(),
				],
				$status
			);
		}

		$applied_modules = is_array( $result['applied_modules'] ?? null )
			? implode( ', ', array_map( 'sanitize_text_field', $result['applied_modules'] ) )
			: 'selected modules';
		$operation_status = sanitize_key( (string) ( $result['status'] ?? 'failed' ) );
		$propagated_sites = (int) ( $result['propagated_sites'] ?? 0 );
		$failed_sites = is_array( $result['failed_sites'] ?? null ) ? $result['failed_sites'] : [];
		$http_status = $operation_status === 'success' ? 200 : ( $operation_status === 'partial' ? 207 : 500 );
		$message = sprintf(
			'Propagated %s to %d site(s).',
			$applied_modules,
			$propagated_sites
		);

		if ( $operation_status === 'partial' ) {
			$message = sprintf(
				'Propagated %s to %d site(s); %d site(s) failed.',
				$applied_modules,
				$propagated_sites,
				count( $failed_sites )
			);
		} elseif ( $operation_status === 'failed' ) {
			$message = sprintf(
				'Propagation failed for %d site(s).',
				count( $failed_sites )
			);
		}

		return new WP_REST_Response(
			[
				'success' => $operation_status === 'success',
				'status'  => $operation_status,
				'message' => $message,
				'result'  => $result,
			],
			$http_status
		);
	}
}
