<?php

namespace WC_Affiliate\Controllers\Common;

defined( 'ABSPATH' ) || exit;

use WC_Affiliate\Models\Referral;

/**
 * Background Process Controller for WC Affiliate Plugin.
 *
 * Handles all background processing tasks including cron jobs, email sending,
 * commission processing, data cleanup, and bulk operations for the affiliate system.
 *
 * @since 1.0.0
 */
class Process {

	/**
	 * Controller constructor
	 *
	 * Initializes the background process controller and registers necessary hooks
	 */
	public function __construct() {
		$this->register_hooks();
	}

	/**
	 * Register hooks for process controller
	 *
	 * Registers all necessary hooks for background processing, cron jobs, and AJAX handlers
	 *
	 * @return void
	 */
	protected function register_hooks(): void {
		// Cron hooks.
		add_action( 'wc_affiliate_daily', array( $this, 'daily_tasks' ) );
		add_action( 'wc_affiliate_weekly', array( $this, 'weekly_tasks' ) );
		add_action( 'wc_affiliate_cleanup', array( $this, 'cleanup_tasks' ) );

		// Background processing hooks.
		// add_action( 'wp_ajax_wc_affiliate_process_commission', array( $this, 'ajax_process_commission' ) );
		// add_action( 'wp_ajax_wc_affiliate_bulk_payout', array( $this, 'ajax_bulk_payout' ) );
		// add_action( 'wp_ajax_wc_affiliate_import_affiliates', array( $this, 'ajax_import_affiliates' ) );

		// Queue processing.
		// add_action( 'wp_ajax_wc_affiliate_process_queue', array( $this, 'process_queue' ) );
		// add_action( 'wp_ajax_nopriv_wc_affiliate_process_queue', array( $this, 'process_queue' ) );

		// Schedule events on activation.
		add_action( 'wp', array( $this, 'schedule_events' ) );

		// Commission recalculation.
		// add_action( 'wc_affiliate_recalculate_commissions', array( $this, 'recalculate_commissions' ), 10, 2 );
	}

	/**
	 * Schedule recurring events
	 */
	public function schedule_events() {
		/**
		 * Action hook fired before scheduling events.
		 */
		do_action( 'wc_affiliate_schedule_events_before' );

		// Daily tasks.
		if ( ! wp_next_scheduled( 'wc_affiliate_daily' ) ) {
			wp_schedule_event( time(), 'daily', 'wc_affiliate_daily' );
		}

		// Weekly tasks.
		if ( ! wp_next_scheduled( 'wc_affiliate_weekly' ) ) {
			wp_schedule_event( time(), 'weekly', 'wc_affiliate_weekly' );
		}

		// Cleanup tasks (monthly).
		if ( ! wp_next_scheduled( 'wc_affiliate_cleanup' ) ) {
			wp_schedule_event( time(), 'monthly', 'wc_affiliate_cleanup' );
		}

		/**
		 * Action hook fired after scheduling events.
		 */
		do_action( 'wc_affiliate_schedule_events_after' );
	}

	/**
	 * Daily tasks
	 */
	public function daily_tasks() {
		/**
		 * Action hook fired before daily tasks execution.
		 */
		do_action( 'wc_affiliate_daily_tasks_before' );

		// Update pending commissions based on order status changes.
		$this->update_pending_commissions();

		// Send daily summary emails if enabled.
		// if ( 'on' === wca_get_option( 'email', 'admin.daily_summary', 'off' ) ) {
		// do_action( 'wc_affiliate_send_daily_summary' );
		// }

		// Sync external data.
		$this->sync_external_data();

		// Clean up expired visits.
		$this->cleanup_expired_visits();

		// Log daily task completion.
		wca_log( 'Daily tasks completed successfully' );

		/**
		 * Action hook fired after daily tasks execution.
		 */
		do_action( 'wc_affiliate_daily_tasks_after' );
	}

	/**
	 * Weekly tasks
	 */
	public function weekly_tasks() {
		// Send weekly reports.
		// if ( 'on' === wca_get_option( 'email', 'admin.weekly_reports', 'off' ) ) {
		// do_action( 'wc_affiliate_send_weekly_reports' );
		// }

		// Update affiliate rankings.
		$this->update_affiliate_rankings();

		// Database maintenance.
		$this->optimize_database_tables();

		// Backup affiliate data.
		// $this->backup_affiliate_data();

		wca_log( 'Weekly tasks completed successfully' );
	}

	/**
	 * Cleanup tasks (monthly)
	 */
	public function cleanup_tasks() {
		// Remove old visit records.
		$this->cleanup_old_visits();

		// Remove old log entries.
		$this->cleanup_old_logs();

		// Remove old email logs.
		$this->cleanup_old_email_logs();

		// Database optimization.
		$this->optimize_database();

		wca_log( 'Cleanup tasks completed successfully' );
	}

	/**
	 * Update pending commissions based on order status changes
	 */
	protected function update_pending_commissions() {
		$referral_model = new Referral();

		// Get all pending referrals using Referral model.
		$pending_referrals = $referral_model->get_referrals(
			array(
				'payment_status' => 'pending',
				'limit'          => 0, // Get all pending referrals.
			)
		);

		foreach ( $pending_referrals as $referral ) {
			$order = wc_get_order( $referral->get( 'order_id' ) );

			if ( ! $order ) {
				continue;
			}

			$order_status = $order->get_status();
			$new_status   = wca_get_option( 'basic', "referral_status.{$order_status}", 'pending' );

			if ( $new_status !== $referral->get( 'payment_status' ) ) {
				// Update referral status using Referral model.
				$referral->set( 'payment_status', $new_status );
				$referral->save();
			}
		}
	}

	/**
	 * Sync external data (documentation, etc.)
	 */
	protected function sync_external_data() {
		// Sync documentation.
		$doc_id = wca_get_option( 'basic', 'general.doc_id' );

		if ( $doc_id ) {
			$response = wp_remote_get( "https://help.codexpert.io/wp-json/wp/v2/docs/?parent={$doc_id}&per_page=20" );

			if ( ! is_wp_error( $response ) ) {
				$docs = json_decode( wp_remote_retrieve_body( $response ), true );
				update_option( 'wc_affiliate_docs_json', $docs );
			}
		}
	}

	/**
	 * Clean up expired visits
	 */
	protected function cleanup_expired_visits() {
		global $wpdb;

		$retention_days = wca_get_option( 'advanced', 'referral.visit_retention_days', 90 );
		$cutoff_time    = time() - ( $retention_days * DAY_IN_SECONDS );

		// Delete old visits that don't have associated referrals.
		$deleted = $wpdb->query(
			$wpdb->prepare(
				"DELETE v FROM {$wpdb->prefix}wca_visits v LEFT JOIN {$wpdb->prefix}wca_referrals r ON v.id = r.visit WHERE v.time < %d AND r.id IS NULL",
				$cutoff_time
			)
		);

		if ( $deleted > 0 ) {
			wca_log( "Cleaned up {$deleted} expired visits" );
		}
	}

	/**
	 * Update affiliate rankings
	 */
	protected function update_affiliate_rankings() {
		global $wpdb;

		// Calculate rankings for different periods
		$periods = array(
			'monthly'   => 30,
			'quarterly' => 90,
			'yearly'    => 365,
		);

		foreach ( $periods as $period => $days ) {
			$start_time = time() - ( $days * DAY_IN_SECONDS );

			$rankings = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT affiliate, COUNT(*) as referrals, SUM(commission) as commissions FROM {$wpdb->prefix}wca_referrals WHERE time > %d AND payment_status IN ('paid', 'pending') GROUP BY affiliate  ORDER BY commissions DESC",
					$start_time
				)
			);

			update_option( "wc_affiliate_rankings_{$period}", $rankings );
		}
	}

	/**
	 * Optimize database tables
	 */
	protected function optimize_database_tables() {
		global $wpdb;

		$tables = array(
			$wpdb->prefix . 'wca_visits',
			$wpdb->prefix . 'wca_referrals',
			$wpdb->prefix . 'wca_transactions',
		);

		foreach ( $tables as $table ) {
			$wpdb->query( "OPTIMIZE TABLE {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		}

		wca_log( 'Database tables optimized' );
	}

	/**
	 * Clean up old visits
	 */
	protected function cleanup_old_visits() {
		global $wpdb;

		$retention_days = wca_get_option( 'advanced', 'referral.visit_retention_days', 365 );
		$cutoff_time    = time() - ( $retention_days * DAY_IN_SECONDS );

		$deleted = $wpdb->query(
			$wpdb->prepare(
				"DELETE FROM {$wpdb->prefix}wca_visits WHERE time < %d",
				$cutoff_time
			)
		);

		if ( $deleted > 0 ) {
			wca_log( "Cleaned up {$deleted} old visit records" );
		}
	}

	/**
	 * Clean up old logs
	 */
	protected function cleanup_old_logs() {
		$log_retention = wca_get_option( 'advanced', 'referral.log_retention_days', 30 );
		$log_file      = WC_AFFILIATE_PLUGIN_DIR . 'logs/wc-affiliate.log';

		if ( file_exists( $log_file ) && is_writable( $log_file ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable
			$lines       = file( $log_file );
			$cutoff_date = wp_date( 'Y-m-d', time() - ( $log_retention * DAY_IN_SECONDS ) );

			$filtered_lines = array();

			foreach ( $lines as $line ) {
				if ( preg_match( '/^\[(\d{4}-\d{2}-\d{2})/', $line, $matches ) ) {
					if ( $matches[1] >= $cutoff_date ) {
						$filtered_lines[] = $line;
					}
				}
			}

			file_put_contents( $log_file, implode( '', $filtered_lines ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
		}
	}

	/**
	 * Clean up old email logs
	 */
	protected function cleanup_old_email_logs() {
		$email_logs     = get_option( 'wc_affiliate_email_log', array() );
		$retention_days = 30;
		$cutoff_time    = time() - ( $retention_days * DAY_IN_SECONDS );

		$filtered_logs = array_filter(
			$email_logs,
			fn( $log ) => strtotime( $log['time'] ) > $cutoff_time
		);

		if ( count( $filtered_logs ) !== count( $email_logs ) ) {
			update_option( 'wc_affiliate_email_log', $filtered_logs );
		}
	}

	/**
	 * Optimize database
	 */
	protected function optimize_database() {
		global $wpdb;

		// Run database optimization.
		$wpdb->query( "ANALYZE TABLE {$wpdb->prefix}wca_visits, {$wpdb->prefix}wca_referrals, {$wpdb->prefix}wca_transactions" );

		// Update table statistics.
		$wpdb->query( "CHECK TABLE {$wpdb->prefix}wca_visits, {$wpdb->prefix}wca_referrals, {$wpdb->prefix}wca_transactions" );
	}

	/**
	 * AJAX: Process commission calculation
	 */
	public function ajax_process_commission() {
		/**
		 * Action hook fired before AJAX commission processing.
		 */
		do_action( 'wc_affiliate_ajax_process_commission_before' );

		check_ajax_referer( 'wc_affiliate_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( -1 );
		}

		if ( ! isset( $_POST['order_id'], $_POST['affiliate_id'] ) ) {
			wp_die( -1 );
		}

		$order_id     = (int) sanitize_text_field( wp_unslash( $_POST['order_id'] ) );
		$affiliate_id = (int) sanitize_text_field( wp_unslash( $_POST['affiliate_id'] ) );

		if ( ! $order_id || ! $affiliate_id ) {
			wp_send_json_error( __( 'Invalid parameters', 'wc-affiliate' ) );
		}

		$order = wc_get_order( $order_id );
		if ( ! $order ) {
			wp_send_json_error( __( 'Order not found', 'wc-affiliate' ) );
		}

		$commission_data = wca_wc_calculate_commissions( $order, $affiliate_id );

		// Allow filtering commission calculation response
		$response_data = apply_filters(
			'wc_affiliate_ajax_commission_response',
			array(
				'commission'           => $commission_data['total_commission'],
				'products'             => $commission_data['products'],
				'formatted_commission' => wca_format_price( $commission_data['total_commission'] ),
			),
			$order_id,
			$affiliate_id,
			$commission_data
		);

		/**
		 * Action hook fired after AJAX commission processing.
		 *
		 * @param array $response_data Response data.
		 * @param int   $order_id      Order ID.
		 * @param int   $affiliate_id  Affiliate ID.
		 */
		do_action( 'wc_affiliate_ajax_process_commission_after', $response_data, $order_id, $affiliate_id );

		wp_send_json_success( $response_data );
	}

	/**
	 * Recalculate commissions for a period
	 */
	// public function recalculate_commissions( $start_date, $end_date ) {
	// **
	// * Action hook fired before commission recalculation.
	// *
	// * @param string $start_date Start date.
	// * @param string $end_date   End date.
	// */
	// do_action( 'wc_affiliate_recalculate_commissions_before', $start_date, $end_date );
	//
	// global $wpdb;
	//
	// $start_time = strtotime( $start_date );
	// $end_time   = strtotime( $end_date );
	//
	// $referrals = $wpdb->get_results(
	// $wpdb->prepare(
	// "SELECT * FROM {$wpdb->prefix}wca_referrals WHERE time BETWEEN %d AND %d",
	// $start_time,
	// $end_time
	// )
	// );
	//
	// $recalculated = 0;
	//
	// foreach ( $referrals as $referral ) {
	// $order = wc_get_order( $referral->order_id );
	//
	// if ( ! $order ) {
	// continue;
	// }
	//
	// $new_commission_data = wca_wc_calculate_commissions( $order, $referral->affiliate );
	//
	// if ( $new_commission_data['total_commission'] !== (float) $referral->commission ) {
	// $wpdb->update(
	// $wpdb->prefix . 'wca_referrals',
	// array(
	// 'commission' => $new_commission_data['total_commission'],
	// 'products'   => wp_json_encode( $new_commission_data['products'] ),
	// ),
	// array( 'id' => $referral->id ),
	// array( '%f', '%s' ),
	// array( '%d' )
	// );
	//
	// ++$recalculated;
	// }
	// }
	//
	// wca_log( "Recalculated {$recalculated} commissions for period {$start_date} to {$end_date}" );
	//
	// **
	// * Action hook fired after commission recalculation.
	// *
	// * @param int    $recalculated Number of recalculated commissions.
	// * @param string $start_date   Start date.
	// * @param string $end_date     End date.
	// */
	// do_action( 'wc_affiliate_recalculate_commissions_after', $recalculated, $start_date, $end_date );
	//
	// return $recalculated;
	// }

	/**
	 * Clear scheduled events (for deactivation)
	 */
	public static function clear_scheduled_events() {
		wp_clear_scheduled_hook( 'wc_affiliate_daily' );
		wp_clear_scheduled_hook( 'wc_affiliate_weekly' );
		wp_clear_scheduled_hook( 'wc_affiliate_cleanup' );
	}
}
