<?php
/**
 * Import guest customer emails from historical WooCommerce orders.
 *
 * @package CartCue
 */

namespace CartCue;

defined( 'ABSPATH' ) || exit;

final class GuestHistoricalImport {

	public const OPTION_IMPORTED = 'cartcue_guest_import_stats';

	/** Default max orders to scan per import run. */
	public const DEFAULT_LIMIT = 10000;

	/** Orders processed per wc_get_orders batch. */
	private const BATCH_SIZE = 100;

	/**
	 * @param int $days_back Only orders created within this many days (0 = all time).
	 * @param int $limit     Maximum orders to scan across all batches.
	 * @return array{imported:int,skipped:int,consent_granted:int,orders_scanned:int,errors:int,message?:string,ran_at?:string}
	 */
	public static function run( int $days_back = 0, int $limit = self::DEFAULT_LIMIT ): array {
		if ( ! function_exists( 'wc_get_orders' ) ) {
			return self::save_stats(
				[
					'imported'        => 0,
					'skipped'         => 0,
					'consent_granted' => 0,
					'orders_scanned'  => 0,
					'errors'          => 1,
					'message'         => __( 'WooCommerce is not available.', 'cartcue-sales-automation' ),
				]
			);
		}

		$days_back = max( 0, $days_back );
		$limit     = max( 1, min( 10000, $limit ) );
		$imported  = 0;
		$skipped   = 0;
		$consented = 0;
		$errors    = 0;
		$scanned   = 0;
		$seen      = [];
		$page      = 1;

		global $wpdb;

		do {
			$args = [
				'type'    => 'shop_order',
				'status'  => array_keys( wc_get_is_paid_statuses() ),
				'limit'   => self::BATCH_SIZE,
				'paged'   => $page,
				'orderby' => 'date',
				'order'   => 'DESC',
				'return'  => 'ids',
			];

			if ( $days_back > 0 ) {
				$args['date_created'] = '>' . gmdate( 'Y-m-d H:i:s', time() - ( $days_back * DAY_IN_SECONDS ) );
			}

			$order_ids = wc_get_orders( $args );
			if ( ! is_array( $order_ids ) ) {
				$order_ids = [];
			}

			foreach ( $order_ids as $order_id ) {
				if ( $scanned >= $limit ) {
					break 2;
				}

				++$scanned;
				$order = wc_get_order( $order_id );
				if ( ! $order instanceof \WC_Order ) {
					continue;
				}

				if ( ! self::is_guest_order( $order ) ) {
					wp_cache_delete( $order_id, 'posts' );
					continue;
				}

				$email = strtolower( trim( $order->get_billing_email() ) );
				if ( ! is_email( $email ) ) {
					++$skipped;
					wp_cache_delete( $order_id, 'posts' );
					continue;
				}

				if ( isset( $seen[ $email ] ) ) {
					++$skipped;
					wp_cache_delete( $order_id, 'posts' );
					continue;
				}
				$seen[ $email ] = true;

				if ( 'yes' === $order->get_meta( MarketingConsent::ORDER_META_KEY, true ) ) {
					MarketingConsent::grant( $email, 'historical_order' );
					++$consented;
				}

				// phpcs:ignore WordPress.DB.DirectDatabaseQuery
				$exists = $wpdb->get_var(
					$wpdb->prepare(
						"SELECT id FROM %i WHERE email = %s AND status IN ('active','triggered','checkout_started','imported') LIMIT 1",
						DB::carts(),
						$email
					)
				);

				if ( $exists ) {
					++$skipped;
					wp_cache_delete( $order_id, 'posts' );
					continue;
				}

				// phpcs:ignore WordPress.DB.DirectDatabaseQuery
				$ok = $wpdb->insert(
					DB::carts(),
					[
						'user_id'                => 0,
						'email'                  => $email,
						'session_token'          => '',
						'cart_contents'          => '[]',
						'total'                  => '0',
						'status'                 => 'imported',
						'checkout_started_at'    => null,
						'checkout_started_fired' => 0,
						'created_at'             => current_time( 'mysql' ),
						'updated_at'             => current_time( 'mysql' ),
					],
					[ '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s' ]
				);

				if ( false === $ok ) {
					++$errors;
				} else {
					++$imported;
				}

				wp_cache_delete( $order_id, 'posts' );
			}

			++$page;
		} while ( count( $order_ids ) === self::BATCH_SIZE && $scanned < $limit );

		$message = '';
		if ( 0 === $scanned ) {
			$message = __( 'No paid orders were found for the selected date range.', 'cartcue-sales-automation' );
		} elseif ( 0 === $imported && 0 === $errors ) {
			$message = __( 'Guest orders were found, but every email is already in CartCue or has no billing address.', 'cartcue-sales-automation' );
		}

		return self::save_stats(
			[
				'imported'        => $imported,
				'skipped'         => $skipped,
				'consent_granted' => $consented,
				'orders_scanned'  => $scanned,
				'errors'          => $errors,
				'message'         => $message,
			]
		);
	}

	private static function is_guest_order( \WC_Order $order ): bool {
		return 0 === (int) $order->get_customer_id();
	}

	/**
	 * @param array<string,mixed> $stats
	 * @return array<string,mixed>
	 */
	private static function save_stats( array $stats ): array {
		$stats['ran_at'] = current_time( 'mysql' );
		update_option( self::OPTION_IMPORTED, $stats, false );
		return $stats;
	}

	public static function last_stats(): array {
		$stats = get_option( self::OPTION_IMPORTED, [] );
		return is_array( $stats ) ? $stats : [];
	}
}
