<?php
/**
 * CLICommands
 *
 * @package CommonFrameworkPlugin
 */

namespace CommonFrameworkPlugin;

use WP_CLI;

/**
 * Creates the CommonFrameworkPlugin post type and shortcodes to output them.
 */
class CLICommands extends \CommonFrameworkPlugin\Module {
	/**
	 * Only register if on an admin page and if fieldmanager plugin is active.
	 *
	 * @return bool
	 */
	public function can_register() {
		return defined( 'WP_CLI' ) && WP_CLI;
	}

	/**
	 * Register our hooks.
	 *
	 * @return void
	 */
	public function register() {
		// WP_CLI::add_command( 'cf-product', 'ProductRules' );
	}

	/**
	 * Downloads Vertiv products.
	 *
	 * This function uses the Vertiv_Framework_Products class to download XML
	 * files for Vertiv products and logs the process in the command line interface.
	 */
	public function download() {
		$vfp = new VertivProducts();

		WP_CLI::line( $this->prepend_info() . "Running 'import_vertiv_products' to download product XML files." );
		WP_CLI::line( $this->prepend_info() . 'This process may take some time. Please wait...' );

		$start = hrtime( true );
		$vfp->import_vertiv_products();
		$end = hrtime( true );

		$total_time = $this->timer( $start, $end );

		WP_CLI::line( $this->prepend_info() . 'Download finished. Please verify that files have been correctly imported.' );
		WP_CLI::line( $this->prepend_info() . "Completed 'cf-product download' with time of " . $total_time );
	}

	/**
	 * Runs a cron job for Vertiv products.
	 *
	 * @param array $args       The arguments passed from the command line.
	 * @param array $assoc_args The associative arguments passed from the command line.
	 */
	public function cronjob( $args, $assoc_args ) {
		$days = $args[0] ?? null;

		if ( null != $days && 1 != $this->validate_argument( $days, 'integer' ) ) {
			WP_CLI::line( $this->prepend_error() . "The first argument for 'cf-product cronjob' must be an integer value." );
			return;
		}

		$days = intval( $days );

		$vfp = new VertivProducts();

		$start = hrtime( true );
		if ( 0 >= $days || null == $days ) {
			WP_CLI::line( $this->prepend_info() . "Running 'cron_job_report' with default timeframe." );
			$vfp->cron_job_report();
		} else {
			WP_CLI::line( $this->prepend_info() . "Running 'cron_job_report' with timeframe of " . $days . ' days.' );
			$vfp->cron_job_report( $days );
		}
		$end = hrtime( true );

		$total_time = $this->timer( $start, $end );

		WP_CLI::line( $this->prepend_info() . "The 'cron_job_report' has finished running." );
		WP_CLI::line( $this->prepend_info() . "Completed 'cf-product cronjob' with time of " . $total_time );
	}

	/**
	 * Calculates the time difference between two points.
	 *
	 * @param int $start The start time in nanoseconds.
	 * @param int $end   The end time in nanoseconds.
	 * @return string The total time in HH:MM:SS format.
	 */
	private function timer( $start, $end ) {
		$raw_seconds = ( $end - $start ) / 1000000000;

		$hours = floor( $raw_seconds / 3600 );
		$raw_seconds -= $hours * 3600;

		$minutes = floor( ( $raw_seconds / 60 ) % 60 );
		$raw_seconds -= $minutes * 60;

		$seconds = $raw_seconds % 60;

		$total_time = '';

		$total_time .= $hours < 10 ? '0' . $hours : $hours;
		$total_time .= ':';
		$total_time .= $minutes < 10 ? '0' . $minutes : $minutes;
		$total_time .= ':';
		$total_time .= $seconds < 10 ? '0' . $seconds : $seconds;

		return $total_time;
	}

	/**
	 * Prepends an info string to a log message.
	 *
	 * @return string A colorized info string.
	 */
	private function prepend_info() {
		return WP_CLI::colorize( '[%CINFO%n] ' );
	}

	/**
	 * Prepends an error string to a log message.
	 *
	 * @return string A colorized error string.
	 */
	private function prepend_error() {
		return WP_CLI::colorize( '[%RERROR%n] ' );
	}

	/**
	 * Validates an argument based on its expected type.
	 *
	 * @param mixed  $arg  The argument to validate.
	 * @param string $type The expected data type (e.g., 'integer', 'string').
	 * @return int   Returns (-1) for invalid type, 0 for failure, and 1 for success.
	 */
	private function validate_argument( $arg, $type ) {
		switch ( $type ) {
			case 'integer':
				if ( 1 == is_numeric( $arg ) && intval( $arg ) == $arg ) {
					return 1;
				}
				break;
			case 'double':
				if ( 1 == is_numeric( $arg ) && floatval( $arg ) == $arg ) {
					return 1;
				}
				break;
			case 'string':
				if ( 1 == is_string( $arg ) ) {
					return 1;
				}
				break;
			case 'array':
				break;
			case 'boolean':
				break;
			default:
				return ( -1 );
		}

		return 0;
	}
}
