<?php
/**
 * WP-CLI commands for Campaign Tracker.
 *
 * @package     EDD\Pro\CampaignTracker\CLI
 * @copyright   Copyright (c) 2025, Sandhills Development, LLC
 * @license     https://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       3.6.3
 */

namespace EDD\Pro\CampaignTracker\CLI;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore

use EDD\EventManagement\SubscriberInterface;

/**
 * Campaign Tracker WP-CLI commands.
 *
 * @since 3.6.3
 */
class CampaignTracker implements SubscriberInterface {

	/**
	 * Returns an array of events that this subscriber wants to listen to.
	 *
	 * @since 3.6.3
	 * @return array
	 */
	public static function get_subscribed_events() {
		return array(
			'init' => array( 'register_cli_command', 99 ),
		);
	}

	/**
	 * Register the WP-CLI command.
	 *
	 * @since 3.6.3
	 * @return void
	 */
	public function register_cli_command() {
		if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
			return;
		}

		\WP_CLI::add_command( 'edd campaign-tracker', $this );
	}

	/**
	 * Add campaign data to orders for testing purposes.
	 *
	 * ## OPTIONS
	 *
	 * --number=<number>
	 * : The number of orders to add campaign data to. Required.
	 *
	 * [--legacy]
	 * : Add legacy serialized campaign data for testing migrations. Without this flag, adds modern individual meta fields.
	 *
	 * ## EXAMPLES
	 *
	 *     # Add modern campaign data to 50 orders
	 *     wp edd campaign-tracker add --number=50
	 *
	 *     # Add legacy serialized data to 100 orders for migration testing
	 *     wp edd campaign-tracker add --number=100 --legacy
	 *
	 * @since 3.6.3
	 *
	 * @param array $args       Positional arguments.
	 * @param array $assoc_args Associative arguments.
	 */
	public function add( $args, $assoc_args ) {
		global $wpdb;

		// Validate required --number parameter.
		if ( empty( $assoc_args['number'] ) ) {
			\WP_CLI::error( 'The --number parameter is required.' );
		}

		$number = absint( $assoc_args['number'] );
		if ( $number <= 0 ) {
			\WP_CLI::error( 'The --number parameter must be a positive integer.' );
		}

		$is_legacy = isset( $assoc_args['legacy'] );

		// Find orders without any campaign data.
		$order_ids = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT o.id
				FROM {$wpdb->prefix}edd_orders o
				LEFT JOIN {$wpdb->prefix}edd_ordermeta om ON (o.id = om.edd_order_id AND om.meta_key = 'eddct_campaign')
				WHERE o.type = 'sale'
				AND om.meta_id IS NULL
				ORDER BY RAND()
				LIMIT %d",
				$number
			)
		);

		if ( empty( $order_ids ) ) {
			\WP_CLI::error( 'No orders found without campaign data.' );
		}

		$found = count( $order_ids );
		if ( $found < $number ) {
			\WP_CLI::warning( "Only found {$found} orders without campaign data (requested {$number})." );
		}

		$mode = $is_legacy ? 'legacy serialized' : 'modern individual';
		\WP_CLI::log( "Adding {$mode} campaign data to {$found} orders..." );

		$progress = \WP_CLI\Utils\make_progress_bar( 'Processing orders', $found );

		$count = 0;
		foreach ( $order_ids as $order_id ) {
			$campaign_data = $this->generate_random_campaign_data();

			if ( $is_legacy ) {
				// Add only the legacy serialized format for testing migration.
				edd_add_order_meta( $order_id, 'eddct_campaign', $campaign_data );
			} else {
				// Add individual meta fields (modern format).
				if ( ! empty( $campaign_data['name'] ) ) {
					edd_add_order_meta( $order_id, '_eddct_campaign_name', $campaign_data['name'] );
				}
				if ( ! empty( $campaign_data['source'] ) ) {
					edd_add_order_meta( $order_id, '_eddct_campaign_source', $campaign_data['source'] );
				}
				if ( ! empty( $campaign_data['medium'] ) ) {
					edd_add_order_meta( $order_id, '_eddct_campaign_medium', $campaign_data['medium'] );
				}
				if ( ! empty( $campaign_data['term'] ) ) {
					edd_add_order_meta( $order_id, '_eddct_campaign_term', $campaign_data['term'] );
				}
				if ( ! empty( $campaign_data['content'] ) ) {
					edd_add_order_meta( $order_id, '_eddct_campaign_content', $campaign_data['content'] );
				}
			}

			++$count;
			$progress->tick();
		}

		$progress->finish();

		\WP_CLI::success( "Successfully added {$mode} campaign data to {$count} orders." );

		// Show migration status if legacy data was added.
		if ( $is_legacy ) {
			$needs_migration = $wpdb->get_var(
				"SELECT COUNT(DISTINCT o.id)
				FROM {$wpdb->prefix}edd_orders o
				INNER JOIN {$wpdb->prefix}edd_ordermeta campaign ON (o.id = campaign.edd_order_id AND campaign.meta_key = 'eddct_campaign')
				LEFT JOIN {$wpdb->prefix}edd_ordermeta name ON (o.id = name.edd_order_id AND name.meta_key = '_eddct_campaign_name')
				WHERE o.type = 'sale'
				AND name.meta_id IS NULL"
			);

			\WP_CLI::log( "\nTotal orders now needing migration: {$needs_migration}" );
		}
	}

	/**
	 * Generate random campaign data with varied completeness.
	 *
	 * @since 3.6.3
	 * @return array Campaign data with name, source, and/or medium.
	 */
	private function generate_random_campaign_data() {
		$campaigns = array(
			// Complete campaign data.
			array(
				'name'   => 'spring_sale_2024',
				'source' => 'google',
				'medium' => 'cpc',
			),
			array(
				'name'   => 'summer_promo',
				'source' => 'facebook',
				'medium' => 'social',
			),
			array(
				'name'   => 'newsletter_weekly',
				'source' => 'email',
				'medium' => 'email',
			),
			array(
				'name'   => 'winter_campaign',
				'source' => 'twitter',
				'medium' => 'social',
			),
			array(
				'name'   => 'affiliate_promo',
				'source' => 'affiliate_network',
				'medium' => 'referral',
			),
			array(
				'name'   => 'black_friday_2023',
				'source' => 'google',
				'medium' => 'cpc',
			),
			array(
				'name'   => 'cyber_monday',
				'source' => 'bing',
				'medium' => 'cpc',
			),
			array(
				'name'   => 'retargeting_campaign',
				'source' => 'facebook',
				'medium' => 'display',
			),
			array(
				'name'   => 'linkedin_b2b',
				'source' => 'linkedin',
				'medium' => 'social',
			),
			array(
				'name'   => 'youtube_ads',
				'source' => 'youtube',
				'medium' => 'video',
			),
			// Partial data - only name and source.
			array(
				'name'   => 'mobile_app_install',
				'source' => 'google_play',
			),
			array(
				'name'   => 'ios_launch',
				'source' => 'app_store',
			),
			// Partial data - only name and medium.
			array(
				'name'   => 'partner_referral',
				'medium' => 'referral',
			),
			array(
				'name'   => 'organic_search',
				'medium' => 'organic',
			),
			// Partial data - only name.
			array(
				'name' => 'direct_traffic',
			),
			array(
				'name' => 'unknown_source',
			),
			// Partial data - source and medium only.
			array(
				'source' => 'instagram',
				'medium' => 'social',
			),
			array(
				'source' => 'pinterest',
				'medium' => 'social',
			),
		);

		return $campaigns[ array_rand( $campaigns ) ];
	}
}
