<?php
/**
 * Order tracking module.
 *
 * @package TrustLens\Modules
 * @since   1.0.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Orders module class.
 *
 * Tracks order activity:
 * - Completed orders
 * - Order values
 * - Cancellation patterns
 *
 * @since 1.0.0
 */
class TrustLens_Module_Orders extends TrustLens_Module {

	/**
	 * Module ID.
	 *
	 * @var string
	 */
	protected string $id = 'orders';

	/**
	 * Module name.
	 *
	 * @var string
	 */
	protected string $name = 'Order Tracking';

	/**
	 * Module description.
	 *
	 * @var string
	 */
	protected string $description = 'Tracks order activity and identifies manipulation patterns.';

	/**
	 * Is Pro feature.
	 *
	 * @var bool
	 */
	protected bool $is_pro = false;

	/**
	 * Register hooks.
	 *
	 * @since 1.0.0
	 */
	public function register_hooks(): void {
		// Track completed orders. Accept the WC_Order passed by WooCommerce
		// (2nd arg) so we don't re-query the order from disk.
		add_action( 'woocommerce_order_status_completed', array( $this, 'handle_order_completed' ), 10, 2 );

		// Track order creation for initial customer record.
		add_action( 'woocommerce_checkout_order_created', array( $this, 'handle_order_created' ) );

		// Track cancellations.
		add_action( 'woocommerce_order_status_cancelled', array( $this, 'handle_order_cancelled' ) );
	}

	/**
	 * Handle order creation.
	 *
	 * @since 1.0.0
	 * @param WC_Order $order Order object.
	 */
	public function handle_order_created( WC_Order $order ): void {
		$customer_key = wstl_get_customer_key( $order );

		// Ensure customer record exists.
		wstl_ensure_customer_record( $customer_key, $order );

		// Update first order date if not set.
		$customer = wstl_get_customer( $customer_key['email_hash'] );

		if ( $customer && empty( $customer->first_order_date ) ) {
			wstl_update_customer( $customer_key['email_hash'], array(
				'first_order_date' => current_time( 'mysql' ),
			) );
		}

		// Log event.
		$this->log_event(
			$customer_key['email_hash'],
			'order_created',
			array(
				'order_id'    => $order->get_id(),
				'order_total' => $order->get_total(),
			),
			$order->get_id()
		);
	}

	/**
	 * Handle order completed.
	 *
	 * @since 1.0.0
	 * @param int           $order_id Order ID.
	 * @param WC_Order|null $order    Order object (WooCommerce passes this as 2nd arg). Optional
	 *                                fallback to wc_get_order() handles any third-party do_action()
	 *                                call that fires the hook with only one argument.
	 */
	public function handle_order_completed( int $order_id, $order = null ): void {
		if ( ! $order instanceof WC_Order ) {
			$order = wc_get_order( $order_id );
		}
		if ( ! $order ) {
			return;
		}

		$customer_key = wstl_get_customer_key( $order );

		// Ensure customer record exists.
		wstl_ensure_customer_record( $customer_key, $order );

		// Update customer stats.
		$this->update_customer_stats( $customer_key['email_hash'], $order );

		// Log event.
		$this->log_event(
			$customer_key['email_hash'],
			'order_completed',
			array(
				'order_id'    => $order_id,
				'order_total' => $order->get_total(),
			),
			$order_id
		);

		// Queue score recalculation.
		$this->queue_score_update( $customer_key['email_hash'] );
	}

	/**
	 * Handle order cancellation.
	 *
	 * @since 1.0.0
	 * @param int $order_id Order ID.
	 */
	public function handle_order_cancelled( int $order_id ): void {
		$order = wc_get_order( $order_id );
		if ( ! $order ) {
			return;
		}

		$customer_key = wstl_get_customer_key( $order );

		// Ensure customer record exists.
		wstl_ensure_customer_record( $customer_key, $order );

		// Increment cancelled orders.
		$repo = new TrustLens_Customer_Repository();
		$repo->increment( $customer_key['email_hash'], 'cancelled_orders' );

		// Log event.
		$this->log_event(
			$customer_key['email_hash'],
			'order_cancelled',
			array(
				'order_id'    => $order_id,
				'order_total' => $order->get_total(),
			),
			$order_id
		);

		// Queue score recalculation.
		$this->queue_score_update( $customer_key['email_hash'] );
	}

	/**
	 * Update customer order stats.
	 *
	 * @since 1.0.0
	 * @param string   $email_hash Customer email hash.
	 * @param WC_Order $order      Order object.
	 */
	private function update_customer_stats( string $email_hash, WC_Order $order ): void {
		global $wpdb;

		$table = $wpdb->prefix . 'trustlens_customers';
		$order_total = $order->get_total();

		// Update order stats and recalculate return rate.
		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix, safe.
		$wpdb->query( $wpdb->prepare(
			"UPDATE {$table}
			 SET
			     total_orders = total_orders + 1,
			     total_order_value = total_order_value + %f,
			     -- total_orders is ALREADY incremented above; MySQL evaluates SET
			     -- assignments left-to-right, so referencing it here yields the new
			     -- value. Do NOT add +1 — that double-counts the denominator
			     -- (off-by-one: 3/12=25.00 instead of the correct 3/11=27.27).
			     return_rate = CASE
			         WHEN total_orders > 0 THEN (total_refunds / total_orders) * 100
			         ELSE 0
			     END,
			     last_order_date = %s,
			     updated_at = %s
			 WHERE email_hash = %s",
			$order_total,
			current_time( 'mysql' ),
			current_time( 'mysql' ),
			$email_hash
		) );
		// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter

		// Also update first order date if not set.
		$customer = wstl_get_customer( $email_hash );
		if ( $customer && empty( $customer->first_order_date ) ) {
			wstl_update_customer( $email_hash, array(
				'first_order_date' => current_time( 'mysql' ),
			) );
		}

		// Invalidate caches.
		$repo = new TrustLens_Customer_Repository();
		$repo->invalidate_caches();
	}

	/**
	 * Calculate signal score.
	 *
	 * @since 1.0.0
	 * @param string $email_hash Customer email hash.
	 * @return array Signal data.
	 */
	public function get_signal( string $email_hash, ?object $customer = null ): array {
		$customer = $customer ?? wstl_get_customer( $email_hash );

		if ( ! $customer ) {
			return array( 'score' => 0, 'reason' => '' );
		}

		$score = 0;
		$reasons = array();

		// Positive: Order history without issues.
		$orders = (int) $customer->total_orders;
		$refunds = (int) $customer->total_refunds;
		$clean_orders = $orders - $refunds;

		if ( $clean_orders >= 10 ) {
			$score += 15;
			$reasons[] = sprintf(
				/* translators: %d: number of orders without issues */
				__( '%d orders without issues', 'trustlens' ),
				$clean_orders
			);
		} elseif ( $clean_orders >= 5 ) {
			$score += 10;
			$reasons[] = sprintf(
				/* translators: %d: number of orders without issues */
				__( '%d orders without issues', 'trustlens' ),
				$clean_orders
			);
		} elseif ( $clean_orders >= 3 ) {
			$score += 5;
		}

		// Positive: High order value.
		$total_value = (float) $customer->total_order_value;
		$refund_value = (float) $customer->total_refund_value;
		$net_value = $total_value - $refund_value;

		if ( $net_value >= 1000 ) {
			$score += 5;
			$reasons[] = sprintf(
				/* translators: %s: formatted currency value */
				__( 'High customer value: %s', 'trustlens' ),
				wp_strip_all_tags( wc_price( $net_value ) )
			);
		}

		// Negative: High cancellation rate.
		$cancelled = (int) $customer->cancelled_orders;

		if ( $orders > 0 && $cancelled >= 3 ) {
			$cancel_rate = ( $cancelled / $orders ) * 100;

			if ( $cancel_rate >= 50 ) {
				$score -= 15;
				$reasons[] = sprintf(
					/* translators: %.0f: cancellation rate percentage */
					__( 'High cancellation rate: %.0f%%', 'trustlens' ),
					$cancel_rate
				);
			} elseif ( $cancel_rate >= 30 ) {
				$score -= 10;
				$reasons[] = sprintf(
					/* translators: %.0f: cancellation rate percentage */
					__( 'Elevated cancellation rate: %.0f%%', 'trustlens' ),
					$cancel_rate
				);
			}
		}

		return array(
			'score'  => $score,
			'reason' => implode( '; ', $reasons ),
		);
	}

	/**
	 * Get settings fields.
	 *
	 * @since 1.0.0
	 * @return array Settings fields.
	 */
	public function get_settings_fields(): array {
		return array();
	}
}
