<?php

namespace WC_Affiliate\Models;

defined( 'ABSPATH' ) || exit;

/**
 * Class ImportJob
 *
 * Handles import job management and data import operations.
 */
class ImportJob {

	/**
	 * Get all import jobs.
	 *
	 * @return array Array of import job data.
	 */
	public static function get_jobs(): array {
		global $wpdb;

		// Use more efficient query with proper prefix matching
		$jobs = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT option_name, option_value
				 FROM {$wpdb->options}
				 WHERE option_name LIKE %s
				 ORDER BY option_id DESC",
				$wpdb->esc_like( 'wc_affiliate_import_job_' ) . '%'
			)
		);

		$import_jobs = array();
		foreach ( $jobs as $job ) {
			$job_data = maybe_unserialize( $job->option_value );
			if ( is_array( $job_data ) ) {
				$import_jobs[] = $job_data;
			}
		}

		return $import_jobs;
	}

	/**
	 * Get import job by ID.
	 *
	 * @param string $job_id Job ID.
	 *
	 * @return array|null Job data or null if not found.
	 */
	public static function get_job( string $job_id ): ?array {
		if ( empty( $job_id ) || ! is_string( $job_id ) ) {
			return null;
		}

		// Sanitize job_id to prevent potential security issues
		$job_id = sanitize_key( $job_id );

		$option_name = 'wc_affiliate_import_job_' . $job_id;
		$job_data    = get_option( $option_name );

		return is_array( $job_data ) ? $job_data : null;
	}

	/**
	 * Save import job.
	 *
	 * @param string $job_id   Job ID.
	 * @param array  $job_data Job data.
	 *
	 * @return bool True on success, false on failure.
	 */
	public static function save_job( string $job_id, array $job_data ): bool {
		if ( empty( $job_id ) || ! is_string( $job_id ) || empty( $job_data ) || ! is_array( $job_data ) ) {
			return false;
		}

		// Sanitize job_id to prevent potential security issues
		$job_id = sanitize_key( $job_id );

		/**
		 * Filter to allow preventing import job save operations.
		 *
		 * @param bool   $can_save Whether the save can proceed.
		 * @param string $job_id   Job ID.
		 * @param array  $job_data Job data.
		 */
		$can_save = apply_filters( 'wc_affiliate_can_save_import_job', true, $job_id, $job_data );
		if ( ! $can_save ) {
			return false;
		}

		/**
		 * Filter to modify import job data before saving.
		 *
		 * @param array  $job_data Job data.
		 * @param string $job_id   Job ID.
		 */
		$job_data = apply_filters( 'wc_affiliate_import_job_save_data', $job_data, $job_id );

		/**
		 * Action hook fired before saving import job.
		 *
		 * @param string $job_id   Job ID.
		 * @param array  $job_data Job data.
		 */
		do_action( 'wc_affiliate_import_job_before_save', $job_id, $job_data );

		$option_name = 'wc_affiliate_import_job_' . $job_id;
		$result      = update_option( $option_name, $job_data );

		/**
		 * Action hook fired after saving import job.
		 *
		 * @param string $job_id   Job ID.
		 * @param array  $job_data Job data.
		 * @param bool   $result   Save result.
		 */
		do_action( 'wc_affiliate_import_job_after_save', $job_id, $job_data, $result );

		return $result;
	}

	/**
	 * Delete import job.
	 *
	 * @param string $job_id Job ID.
	 *
	 * @return bool True on success, false on failure.
	 */
	public static function delete_job( string $job_id ): bool {
		if ( empty( $job_id ) || ! is_string( $job_id ) ) {
			return false;
		}

		// Sanitize job_id to prevent potential security issues
		$job_id = sanitize_key( $job_id );

		/**
		 * Filter to allow preventing import job delete operations.
		 *
		 * @param bool   $can_delete Whether the delete can proceed.
		 * @param string $job_id     Job ID.
		 */
		$can_delete = apply_filters( 'wc_affiliate_can_delete_import_job', true, $job_id );
		if ( ! $can_delete ) {
			return false;
		}

		/**
		 * Action hook fired before deleting import job.
		 *
		 * @param string $job_id Job ID.
		 */
		do_action( 'wc_affiliate_import_job_before_delete', $job_id );

		$option_name = 'wc_affiliate_import_job_' . $job_id;
		$result      = delete_option( $option_name );

		/**
		 * Action hook fired after deleting import job.
		 *
		 * @param string $job_id Job ID.
		 * @param bool   $result Delete result.
		 */
		do_action( 'wc_affiliate_import_job_after_delete', $job_id, $result );

		return $result;
	}

	/**
	 * Clean up old import jobs.
	 *
	 * @param int $days Days to keep jobs.
	 *
	 * @return int Number of jobs cleaned up.
	 */
	public static function cleanup_old_jobs( int $days = 30 ): int {
		/**
		 * Filter to allow preventing import job cleanup operations.
		 *
		 * @param bool $can_cleanup Whether the cleanup can proceed.
		 * @param int  $days        Days to keep jobs.
		 */
		$can_cleanup = apply_filters( 'wc_affiliate_can_cleanup_import_jobs', true, $days );
		if ( ! $can_cleanup ) {
			return 0;
		}

		/**
		 * Filter to modify cleanup days.
		 *
		 * @param int $days Days to keep jobs.
		 */
		$days = apply_filters( 'wc_affiliate_import_job_cleanup_days', $days );

		/**
		 * Action hook fired before cleaning up old import jobs.
		 *
		 * @param int $days Days to keep jobs.
		 */
		do_action( 'wc_affiliate_import_job_before_cleanup', $days );

		global $wpdb;
		$cutoff_time = time() - ( $days * DAY_IN_SECONDS );
		$deleted_count = 0;

		// Use direct SQL for better performance and memory efficiency
		$jobs_to_delete = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT option_name
				 FROM {$wpdb->options}
				 WHERE option_name LIKE %s
				 AND option_value IS NOT NULL",
				$wpdb->esc_like( 'wc_affiliate_import_job_' ) . '%'
			)
		);

		foreach ( $jobs_to_delete as $option_name ) {
			$job_data = get_option( $option_name );
			if ( is_array( $job_data ) && isset( $job_data['created_at'] ) && $job_data['created_at'] < $cutoff_time ) {
				delete_option( $option_name );
				++$deleted_count;
			}
		}

		/**
		 * Action hook fired after cleaning up old import jobs.
		 *
		 * @param int $deleted_count Number of jobs cleaned up.
		 * @param int $days          Days to keep jobs.
		 */
		do_action( 'wc_affiliate_import_job_after_cleanup', $deleted_count, $days );

		return $deleted_count;
	}
}
