<?php

namespace Simple_History\Loggers;

use Simple_History\Event_Details\Event_Details_Group;
use Simple_History\Event_Details\Event_Details_Group_Table_Formatter;
use Simple_History\Event_Details\Event_Details_Item;
use Simple_History\Helpers;

/**
 * Logger for the Redirection plugin
 * https://wordpress.org/plugins/redirection/
 */
class Plugin_Redirection_Logger extends Logger {
	/**
	 * Logger slug.
	 *
	 * @var string
	 */
	public $slug = 'Plugin_Redirection';

	/**
	 * Return info about logger.
	 *
	 * @return array Array with plugin info.
	 */
	public function get_info() {

		return array(
			'name'        => _x( 'Plugin: Redirection Logger', 'Logger: Redirection', 'simple-history' ),
			'description' => _x( 'Logs edits in the Redirection plugin', 'Logger: Redirection', 'simple-history' ),
			'name_via'    => _x( 'In plugin Redirection', 'Logger: Redirection', 'simple-history' ),
			'capability'  => 'manage_options',
			'messages'    => array(
				'redirection_redirection_added'    => _x( 'Added a redirection for URL "{source_url}"', 'Logger: Redirection', 'simple-history' ),
				'redirection_redirection_edited'   => _x( 'Edited redirection for URL "{prev_source_url}"', 'Logger: Redirection', 'simple-history' ),
				'redirection_redirection_enabled'  => _x( 'Enabled redirection for {items_count} URL(s)', 'Logger: Redirection', 'simple-history' ),
				'redirection_redirection_disabled' => _x( 'Disabled redirection for {items_count} URL(s)', 'Logger: Redirection', 'simple-history' ),
				'redirection_redirection_deleted'  => _x( 'Deleted redirection for {items_count} URL(s)', 'Logger: Redirection', 'simple-history' ),
				'redirection_options_saved'        => _x( 'Updated redirection options', 'Logger: Redirection', 'simple-history' ),
				'redirection_options_removed_all'  => _x( 'Removed all redirection options and deactivated plugin', 'Logger: Redirection', 'simple-history' ),
				'redirection_group_added'          => _x( 'Added redirection group "{group_name}"', 'Logger: Redirection', 'simple-history' ),
				'redirection_group_edited'         => _x( 'Edited redirection group "{prev_group_name}"', 'Logger: Redirection', 'simple-history' ),
				'redirection_group_enabled'        => _x( 'Enabled {items_count} redirection group(s)', 'Logger: Redirection', 'simple-history' ),
				'redirection_group_disabled'       => _x( 'Disabled {items_count} redirection group(s)', 'Logger: Redirection', 'simple-history' ),
				'redirection_group_deleted'        => _x( 'Deleted {items_count} redirection group(s)', 'Logger: Redirection', 'simple-history' ),
			),
			'labels'      => array(
				'search' => array(
					'label'     => _x( 'Redirection', 'Redirection logger: search', 'simple-history' ),
					'label_all' => _x( 'All Redirection activity', 'Redirection logger: search', 'simple-history' ),
					'options'   => array(
						_x( 'Redirections added', 'Redirection logger: search', 'simple-history' ) => array(
							'redirection_redirection_added',
						),
						_x( 'Redirections modified', 'Redirection logger: search', 'simple-history' ) => array(
							'redirection_redirection_edited',
							'redirection_redirection_enabled',
							'redirection_redirection_disabled',
						),
						_x( 'Redirections deleted', 'Redirection logger: search', 'simple-history' ) => array(
							'redirection_redirection_deleted',
						),
						_x( 'Redirection groups', 'Redirection logger: search', 'simple-history' ) => array(
							'redirection_group_added',
							'redirection_group_edited',
							'redirection_group_enabled',
							'redirection_group_disabled',
							'redirection_group_deleted',
						),
						_x( 'Redirection options', 'Redirection logger: search', 'simple-history' ) => array(
							'redirection_options_saved',
							'redirection_options_removed_all',
						),
					),
				),
			),
		);
	}

	/**
	 * Called when logger is loaded.
	 */
	public function loaded() {

		// Check that Redirection class exists.
		if ( ! class_exists( 'Red_Item' ) ) {
			return;
		}

		// Redirection plugin uses the WP REST API, so catch when requests do the API is done.
		// We use filter *_before_callbacks so we can access the old title
		// of the Redirection object, i.e. before new values are saved.
		add_filter( 'rest_request_before_callbacks', array( $this, 'on_rest_request_before_callbacks' ), 10, 3 );
	}

	/**
	 * Fired when WP REST API call is done.
	 *
	 * @param \WP_HTTP_Response $response Result to send to the client. Usually a WP_REST_Response.
	 * @param \WP_REST_Server   $handler  ResponseHandler instance (usually WP_REST_Server).
	 * @param \WP_REST_Request  $request  Request used to generate the response.
	 *
	 * @return \WP_HTTP_Response $response
	 */
	public function on_rest_request_before_callbacks( $response, $handler, $request ) {
		// Callback must be set.
		if ( ! isset( $handler['callback'] ) ) {
			return $response;
		}

		$callback = $handler['callback'];

		$callable_name = Helpers::get_callable_name( $callback );

		$ok_redirection_api_callable_names = array(
			'Redirection_Api_Redirect::route_bulk',
			'Redirection_Api_Redirect::route_create',
			'Redirection_Api_Redirect::route_update',
			'Redirection_Api_Group::route_create',
			'Redirection_Api_Group::route_bulk',
			'Redirection_Api_Group::route_update',
			'Redirection_Api_Settings::route_save_settings',
		);

		// Bail directly if this is not a Redirection API call.
		if ( ! in_array( $callable_name, $ok_redirection_api_callable_names, true ) ) {
			return $response;
		}

		if ( $callable_name === 'Redirection_Api_Redirect::route_create' ) {
			$this->log_redirection_add( $request );
		} elseif ( $callable_name === 'Redirection_Api_Redirect::route_update' ) {
			$this->log_redirection_edit( $request );
		} elseif ( $callable_name === 'Redirection_Api_Redirect::route_bulk' ) {
			$bulk_action = $request->get_param( 'bulk' );
			$bulk_items  = $request->get_param( 'items' );

			if ( ! is_array( $bulk_items ) ) {
				$bulk_items = explode( ',', $bulk_items );
			}

			$bulk_items = array_map( 'intval', $bulk_items );

			if ( empty( $bulk_items ) ) {
				return $response;
			}

			if ( $bulk_action === 'enable' ) {
				$this->log_redirection_enable_or_disable( $request, $bulk_items );
			} elseif ( $bulk_action === 'disable' ) {
				$this->log_redirection_enable_or_disable( $request, $bulk_items );
			} elseif ( $bulk_action === 'delete' ) {
				$this->log_redirection_delete( $request, $bulk_items );
			}
		} elseif ( $callable_name === 'Redirection_Api_Group::route_create' ) {
			$this->log_group_add( $request );
		} elseif ( $callable_name === 'Redirection_Api_Group::route_update' ) {
			$this->log_group_edit( $request );
		} elseif ( $callable_name === 'Redirection_Api_Group::route_bulk' ) {
			$bulk_action = $request->get_param( 'bulk' );
			$bulk_items  = (array) $request->get_param( 'items' );

			$bulk_items = array_map( 'intval', $bulk_items );

			if ( empty( $bulk_items ) ) {
				return $response;
			}

			if ( $bulk_action === 'enable' ) {
				$this->log_group_enable_or_disable( $request, $bulk_items );
			} elseif ( $bulk_action === 'disable' ) {
				$this->log_group_enable_or_disable( $request, $bulk_items );
			} elseif ( $bulk_action === 'delete' ) {
				$this->log_group_delete( $request, $bulk_items );
			}
		} elseif ( $callable_name === 'Redirection_Api_Settings::route_save_settings' ) {
			$this->log_options_save( $request );
		}

		return $response;
	}

	/**
	 * Log when a Redirection group is deleted.
	 *
	 * @param \WP_REST_Request $req Request.
	 * @param array            $bulk_items Array with item ids.
	 */
	public function log_group_delete( $req, $bulk_items ) {
		$context = array(
			'items'       => $bulk_items,
			'items_count' => count( $bulk_items ),
		);

		$this->info_message(
			'redirection_group_deleted',
			$context
		);
	}

	/**
	 * Log when a Redirection group is added.
	 *
	 * @param \WP_REST_Request $req Request.
	 */
	public function log_group_add( $req ) {
		$group_name = $req->get_param( 'name' );

		if ( ! $group_name ) {
			return;
		}

		$context = array(
			'group_name' => $group_name,
		);

		$this->info_message(
			'redirection_group_added',
			$context
		);
	}

	/**
	 * Log when a Redirection group is edited.
	 *
	 * @param \WP_REST_Request $req Request.
	 */
	public function log_group_edit( $req ) {
		$group_id = $req->get_param( 'id' );

		if ( $group_id === null ) {
			return;
		}

		$context = array(
			'group_id'            => $group_id,
			'new_group_name'      => $req->get_param( 'name' ),
			'new_group_module_id' => $req->get_param( 'moduleId' ),
		);

		// Get old values.
		$redirection_item = \Red_Group::get( $group_id );
		if ( $redirection_item !== false ) {
			$prev_group_name      = $redirection_item->get_name();
			$prev_group_module_id = $redirection_item->get_module_id();

			$context['prev_group_name']      = $prev_group_name;
			$context['prev_group_module_id'] = $prev_group_module_id;
		}

		$this->info_message(
			'redirection_group_edited',
			$context
		);
	}

	/**
	 * Log enabling and disabling of redirection groups.
	 *
	 * @param object $req Request.
	 * @param array  $bulk_items Array with item ids.
	 */
	public function log_group_enable_or_disable( $req, $bulk_items ) {
		$bulk_action = $req->get_param( 'bulk' );

		$message_key = $bulk_action === 'enable' ? 'redirection_group_enabled' : 'redirection_group_disabled';

		$context = array(
			'items'       => $bulk_items,
			'items_count' => count( $bulk_items ),
		);

		$this->info_message(
			$message_key,
			$context
		);
	}

	/**
	 * Log when options are saved.
	 *
	 * @param object $req Request.
	 */
	protected function log_options_save( $req ) {
		$this->info_message( 'redirection_options_saved' );
	}

	/**
	 * Log the deletion of a redirection.
	 *
	 * @param object $req Request.
	 * @param array  $bulk_items Array with item ids.
	 */
	protected function log_redirection_delete( $req, $bulk_items ) {
		$context = array(
			'items'       => $bulk_items,
			'items_count' => count( $bulk_items ),
		);

		$message_key = 'redirection_redirection_deleted';

		$this->info_message(
			$message_key,
			$context
		);
	}

	/**
	 * Log enable or disable of items.
	 *
	 * @param object $req Req.
	 * @param array  $bulk_items Array.
	 */
	protected function log_redirection_enable_or_disable( $req, $bulk_items ) {
		$bulk_action = $req->get_param( 'bulk' );

		$message_key = $bulk_action === 'enable' ? 'redirection_redirection_enabled' : 'redirection_redirection_disabled';

		$context = array(
			'items'       => $bulk_items,
			'items_count' => count( $bulk_items ),
		);

		$this->info_message(
			$message_key,
			$context
		);
	}

	/**
	 * Log when a Redirection is added.
	 *
	 * @param \WP_REST_Request $req Request.
	 */
	protected function log_redirection_add( $req ) {
		$action_data = $req->get_param( 'action_data' );

		if ( ! $action_data || ! is_array( $action_data ) ) {
			return false;
		}

		$context = array(
			'source_url' => $req->get_param( 'url' ),
			'target_url' => $action_data['url'],
		);

		$this->info_message( 'redirection_redirection_added', $context );
	}

	/**
	 * Log when a Redirection is changed.
	 *
	 * @param \WP_REST_Request $req Request.
	 */
	protected function log_redirection_edit( $req ) {
		$action_data = $req->get_param( 'action_data' );

		if ( ! $action_data || ! is_array( $action_data ) ) {
			return false;
		}

		$redirection_id = $req->get_param( 'id' );

		$context = array(
			'new_source_url' => $req->get_param( 'url' ),
			'new_target'     => $action_data['url'],
			'redirection_id' => $redirection_id,
		);

		// Get old values.
		$redirection_item = \Red_Item::get_by_id( $redirection_id );

		if ( $redirection_item !== false ) {
			$context['prev_source_url'] = $redirection_item->get_url();
			$context['prev_target']     = maybe_unserialize( $redirection_item->get_action_data() );
		}

		$this->info_message(
			'redirection_redirection_edited',
			$context
		);
	}

	/**
	 * Return more info about an logged redirection event.
	 *
	 * @param object $row Row with info.
	 */
	public function get_log_row_details_output( $row ) {
		$context     = $row->context;
		$message_key = $context['_message_key'];

		if ( $message_key !== 'redirection_redirection_edited' ) {
			return '';
		}

		$group = new Event_Details_Group();
		$group->set_formatter( new Event_Details_Group_Table_Formatter() );

		$group->add_items( [
			new Event_Details_Item(
				[ 'new_source_url', 'prev_source_url' ],
				_x( 'Source URL', 'Logger: Redirection', 'simple-history' ),
			),
			new Event_Details_Item(
				[ 'new_target', 'prev_target' ],
				_x( 'Target', 'Logger: Redirection', 'simple-history' ),
			),
		] );

		return $group;
	}
}
