<?php
/**
 * Order querying and recovery tracking.
 *
 * @package FailedOrderRescueForWooCommerce
 */

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

class FORD_Orders {
	/**
	 * Initialize hooks.
	 *
	 * @return void
	 */
	public static function init() {
		add_action( 'woocommerce_order_status_changed', array( __CLASS__, 'maybe_mark_recovered' ), 10, 4 );
	}

	/**
	 * Recoverable order statuses selected by settings.
	 *
	 * @return array
	 */
	public static function recoverable_statuses() {
		return array_values( array_filter( (array) FORD_Settings::get( 'enabled_statuses' ) ) );
	}

	/**
	 * Get recoverable orders.
	 *
	 * @param int $limit Number of orders.
	 * @return array
	 */
	public static function get_recoverable_orders( $limit = 20 ) {
		if ( ! function_exists( 'wc_get_orders' ) ) {
			return array();
		}

		$orders = wc_get_orders(
			array(
				'limit'   => max( 1, absint( $limit ) * 2 ),
				'status'  => self::recoverable_statuses(),
				'orderby' => 'date',
				'order'   => 'DESC',
				'return'  => 'objects',
			)
		);

		$orders = array_filter(
			$orders,
			static function ( $order ) {
				return $order instanceof WC_Order && 'yes' !== $order->get_meta( '_ford_ignored', true );
			}
		);

		return array_slice( array_values( $orders ), 0, absint( $limit ) );
	}

	/**
	 * Dashboard totals.
	 *
	 * @return array
	 */
	public static function get_dashboard_stats() {
		$since = gmdate( 'Y-m-d H:i:s', strtotime( '-30 days' ) );

		$recoverable = wc_get_orders(
			array(
				'limit'        => -1,
				'status'       => self::recoverable_statuses(),
				'date_created' => '>' . $since,
				'return'       => 'objects',
			)
		);

		$paid_orders = wc_get_orders(
			array(
				'limit'        => -1,
				'status'       => array( 'processing', 'completed' ),
				'date_created' => '>' . $since,
				'return'       => 'objects',
			)
		);

		$recovered = array_filter(
			$paid_orders,
			static function ( $order ) {
				return $order instanceof WC_Order && 'yes' === $order->get_meta( '_ford_recovered_via_plugin', true );
			}
		);

		return array(
			'lost_revenue'       => self::sum_orders( $recoverable ),
			'recoverable_count'  => count( $recoverable ),
			'recovered_revenue'  => self::sum_orders( $recovered ),
			'recovered_count'    => count( $recovered ),
		);
	}

	/**
	 * Sum order totals.
	 *
	 * @param array $orders Order objects.
	 * @return float
	 */
	public static function sum_orders( $orders ) {
		$total = 0.0;

		foreach ( $orders as $order ) {
			if ( $order instanceof WC_Order ) {
				$total += (float) $order->get_total();
			}
		}

		return $total;
	}

	/**
	 * Mark orders as recovered when a previously recoverable order is paid.
	 *
	 * @param int      $order_id Order ID.
	 * @param string   $old_status Old status without wc- prefix.
	 * @param string   $new_status New status without wc- prefix.
	 * @param WC_Order $order Order object.
	 * @return void
	 */
	public static function maybe_mark_recovered( $order_id, $old_status, $new_status, $order ) {
		if ( ! $order instanceof WC_Order ) {
			return;
		}

		if ( ! in_array( $new_status, array( 'processing', 'completed' ), true ) ) {
			return;
		}

		$was_recoverable = in_array( $old_status, self::recoverable_statuses(), true );
		$email_sent      = 'yes' === $order->get_meta( '_ford_recovery_email_sent', true );

		if ( ! $was_recoverable && ! $email_sent ) {
			return;
		}

		$order->update_meta_data( '_ford_recovered_via_plugin', 'yes' );
		$order->update_meta_data( '_ford_recovered_total', $order->get_total() );
		$order->save();
	}
}
