<?php

namespace SovereignStack\SecuritySafe;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

require_once( SECSAFE_DIR_ADMIN_TABLES . '/Table.php' );

/**
 * Class TableAllowDeny
 *
 * @package SecuritySafe
 */
final class TableAllowDeny extends Table {

	/**
	 * Get a list of columns. The format is:
	 * 'internal-name' => 'Title'
	 *
	 * @package WordPress
	 * @since   3.1.0
	 * @abstract
	 *
	 * @return array
	 */
	function get_columns() {

		return [
			'cb' => '<input type="checkbox" />',
			'date' => __( 'Date Added', 'security-safe' ),
			'expire_status' => __( 'Status', 'security-safe' ),
			'status' => __( 'Rule', 'security-safe' ),
			'ip' => __( 'IP Address', 'security-safe' ),
			'date_expire' => __( 'Expires', 'security-safe' ),
			'details' => __( 'Notes', 'security-safe' ),
		];
	}

	function column_expire_status( $item ) {

		return ( $item->date_expire == '0000-00-00 00:00:00' || date( 'Y-m-d H:i:s' ) < $item->date_expire ) ? __( 'active', 'security-safe' ) : __( 'expired', 'security-safe' );
	}

	function extra_tools() {

		$this->add_ip_form();
		$this->search_box( __( 'Search IPs', 'security-safe' ), 'log' );
	}

	/**
	 * Creates Add IP form for the Allow/Deny table
	 *
	 * @return  html
	 */
	protected function add_ip_form() {

		/**
		 * @todo  I need to make this affect all tables.
		 * @date( 2090916)
		 */
		$bulk_actions = $this->get_bulk_actions();

		if( isset( $bulk_actions['delete'] ) ) {

			// Add bulk delete nonce
			wp_nonce_field( SECSAFE_SLUG . '-bulk-delete', '_nonce_bulk_delete' );
		}

		echo '<p class="add_ip_form">';

		wp_nonce_field( SECSAFE_SLUG . '-add-ip', '_nonce_add_ip' );

		echo '<input name="ip" type="text" value="" placeholder="' . esc_html__( 'IP Address', 'security-safe' ) . '">' . '<select name="ip_rule">' . '<option value="">- ' . esc_html__( 'Rule', 'security-safe' ) . ' -</option>' . '<option value="allow">' . esc_html__( 'allow', 'security-safe' ) . '</option>' . '<option value="deny">' . esc_html__( 'deny', 'security-safe' ) . '</option>' . '</select>' . '<select name="ip_expire">' . '<option value="">- ' . esc_html__( 'Timespan', 'security-safe' ) . ' -</option>' . '<option value="1">1 ' . esc_html__( 'day', 'security-safe' ) . '</option>' . '<option value="3">3 ' . esc_html__( 'days', 'security-safe' ) . '</option>' . '<option value="7">7 ' . esc_html__( 'days', 'security-safe' ) . '</option>' . '<option value="30">1 ' . esc_html__( 'month', 'security-safe' ) . '</option>' . '<option value="90">3 ' . esc_html__( 'months', 'security-safe' ) . '</option>' . '<option value="180">6 ' . esc_html__( 'months', 'security-safe' ) . '</option>' . '<option value="999">' . esc_html__( 'forever', 'security-safe' ) . '</option>' . '</select>' . '<input name="ip_details" type="text" value="" placeholder="' . esc_html__( 'Notes', 'security-safe' ) . '">' . '<input type="submit" name="ip_submit" class="button" value="' . esc_html__( 'Add IP', 'security-safe' ) . '" />' . '</p>';
	}

	/**
	 * Get an associative array ( option_name => option_title ) with the list
	 * of bulk actions available on this table.
	 *
	 * @package WordPress
	 * @since   3.1.0
	 *
	 * @return array
	 */
	function get_bulk_actions() {

		return [
			'delete' => __( 'Delete', 'security-safe' ),
		];
	}

	/**
	 * Handles the logic for adding an IP allow/deny rule to db
	 */
	function add_ip() {

		global $SecuritySafe;

		if( ! isset( $_POST['action'] ) && isset( $_POST['ip'] ) && $_POST['ip'] !== '' && isset( $_POST['ip_rule'] ) && $_POST['ip_rule'] !== '' && isset( $_POST['ip_expire'] ) && $_POST['ip_expire'] !== '' ) {

			// Security Check
			if( ! wp_verify_nonce( REQUEST::text_field( '_nonce_add_ip' ), SECSAFE_SLUG . '-add-ip' ) ) {

				$this->messages[] = [
					__( 'Error: IP address not added. Your session expired. Please try again.', 'security-safe' ),
					3,
				];

				return; // Bail

			}

			$ip = filter_var( $_POST['ip'], FILTER_VALIDATE_IP );
			$expire = filter_var( $_POST['ip_expire'], FILTER_VALIDATE_INT );

			if( $ip && $expire !== false ) {

				// Valid IP Address

				$args = [];
				$args['date_expire'] = ( $expire == '999' ) ? '0000-00-00 00:00:00' : date( 'Y-m-d H:i:s', strtotime( "+" . abs( $expire ) . " day" ) );
				$args['ip'] = $ip;
				$args['status'] = ( $_POST['ip_rule'] == 'deny' ) ? 'deny' : 'allow';
				$args['details'] = REQUEST::text_field( 'ip_details' );
				$args['type'] = $type = 'allow_deny'; // Sanitized

				$result = $this->is_ip_whitelisted( $ip );

				if( $result ) {

					$SecuritySafe->messages[] = [
						sprintf( __( 'Notice: %1$s -  IP address is already in the database.', 'security-safe' ), $ip ),
						2,
						0,
					];
				} else {

					$result = Janitor::add_entry( $args );

					if( $result ) {

						$SecuritySafe->messages[] = [
							sprintf( __( '%1$s - IP address added with %2$s rule.', 'security-safe' ), $ip, $args['status'] ),
							0,
							0,
						];
					} else {

						$SecuritySafe->messages[] = [
							sprintf( __( 'Error: %1$s - IP address could not be added. Unknown reason.', 'security-safe' ), $ip ),
							3,
							0,
						];
					}
				}
			} else {

				if( ! $ip ) {

					$SecuritySafe->messages[] = [
						sprintf( __( 'Error: %s - IP address not valid.', 'security-safe' ), esc_html( REQUEST::text_field( 'ip' ) ) ),
						3,
						0,
					];
				} else {

					$SecuritySafe->messages[] = [
						sprintf( __( 'Error: %s - Timespan not valid.', 'security-safe' ), esc_html( REQUEST::text_field( 'ip_expire' ) ) ),
						3,
						0,
					];
				}
			}
		}
	}

	/**
	 * @todo  This needs functionality needs to be moved elsewhere. It is possibly duplicate.
	 * 02/22/2020
	 */
	protected function is_ip_whitelisted( $ip ) {

		global $wpdb;

		$ip = filter_var( $ip, FILTER_VALIDATE_IP );
		$table_main = Yoda::get_table_main();

		$values = [
			$table_main,
			$ip,
		];

		// Verify the IP is not already in db
		$sql = $wpdb->prepare( "SELECT ip FROM %i WHERE type = 'allow_deny' AND ip = %s LIMIT 1", $values );
		$results = $wpdb->get_results( $sql, ARRAY_A );

		return $results;
	}

	/**
	 * @todo  This needs functionality needs to be made accessible outside of this page so that
	 * the message could be displayed on any page in the Admin.
	 * 02/22/2020
	 */
	public function check_whitelist() {

		global $SecuritySafe;

		$ip = Yoda::get_ip();

		if( $ip != '::1' ) {

			$whitelisted = $this->is_ip_whitelisted( $ip );

			if( ! $whitelisted ) {

				$SecuritySafe->messages[] = [
					sprintf( __( '%s We recommend adding your IP to the allow list using the form below.', 'security-safe' ), $ip ),
					2,
					0,
				];
			}
		}
	}

	/**
	 * Set the type of data to display
	 *
	 * @since  2.0.0
	 */
	protected function set_type() {

		$this->type = 'allow_deny';
	}

	/**
	 * Get the array of searchable columns in the database
	 *
	 * @since  2.0.0
	 * @return  array An unassociated array.
	 */
	protected function get_searchable_columns() {

		return [
			'ip',
		];
	}
}
