<?php
/**
 * WooCommerce expired session cleanup task.
 *
 * @package DatabaseCleanup
 */

namespace DatabaseCleanup\Includes\Tasks;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Task_Woocommerce_Sessions extends Abstract_Cleanup_Task {

	public function get_id(): string {
		return 'woocommerce_sessions';
	}

	public function get_label(): string {
		return __( 'WooCommerce sessions', 'wp-powersuite' );
	}

	public function get_description(): string {
		return __( 'Remove expired guest/customer sessions from the WooCommerce sessions table. Active sessions are kept.', 'wp-powersuite' );
	}

	public function is_safe(): bool {
		return true;
	}

	public static function is_available(): bool {
		return class_exists( 'WooCommerce' );
	}

	private function table_name(): string {
		global $wpdb;

		return $wpdb->prefix . 'woocommerce_sessions';
	}

	private function table_exists(): bool {
		global $wpdb;

		$table = $this->table_name();

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		return $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) === $table;
	}

	public function scan( array $settings ): array {
		if ( ! self::is_available() || ! $this->table_exists() ) {
			return [ 'count' => 0, 'estimated_bytes' => 0, 'details' => [] ];
		}

		global $wpdb;

		$now   = time();
		$table = $this->table_name();

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$count = (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(*) FROM `{$table}` WHERE session_expiry > 0 AND session_expiry < %d",
				$now
			)
		);

		return [
			'count'           => $count,
			'estimated_bytes' => $this->estimate_row_bytes( $count, 1024 ),
			'details'         => [],
		];
	}

	public function clean( array $settings, int $batch_size, mixed $cursor = null ): array {
		unset( $settings, $cursor );

		if ( ! self::is_available() || ! $this->table_exists() ) {
			return [ 'deleted' => 0, 'done' => true, 'cursor' => null, 'bytes' => 0 ];
		}

		global $wpdb;

		$now   = time();
		$table = $this->table_name();

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$keys = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT session_key FROM `{$table}` WHERE session_expiry > 0 AND session_expiry < %d ORDER BY session_expiry ASC LIMIT %d",
				$now,
				$batch_size
			)
		);

		$deleted = 0;
		$bytes   = 0;

		foreach ( (array) $keys as $key ) {
			$key = (string) $key;
			if ( $key === '' ) {
				continue;
			}

			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$result = $wpdb->delete( $table, [ 'session_key' => $key ], [ '%s' ] );
			if ( $result ) {
				++$deleted;
				$bytes += 1024;
			}
		}

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$remaining = (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(*) FROM `{$table}` WHERE session_expiry > 0 AND session_expiry < %d",
				$now
			)
		);

		return [
			'deleted' => $deleted,
			'done'    => $remaining === 0,
			'cursor'  => null,
			'bytes'   => $bytes,
		];
	}
}
