<?php
/**
 * Return abuse detection module.
 *
 * @package TrustLens\Modules
 * @since   1.0.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Returns module class.
 *
 * Detects return abuse patterns:
 * - High return rate
 * - Full refund ratio (wardrobing indicator)
 * - Return timing patterns
 *
 * @since 1.0.0
 */
class TrustLens_Module_Returns extends TrustLens_Module {

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

	/**
	 * Module name.
	 *
	 * @var string
	 */
	protected string $name = 'Return Abuse Detection';

	/**
	 * Module description.
	 *
	 * @var string
	 */
	protected string $description = 'Tracks refund patterns and identifies serial returners.';

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

	/**
	 * Register hooks.
	 *
	 * @since 1.0.0
	 */
	public function register_hooks(): void {
		add_action( 'woocommerce_order_refunded', array( $this, 'handle_refund' ), 10, 2 );
	}

	/**
	 * Handle refund event.
	 *
	 * @since 1.0.0
	 * @param int $order_id  Order ID.
	 * @param int $refund_id Refund ID.
	 */
	public function handle_refund( int $order_id, int $refund_id ): void {
		$order = wc_get_order( $order_id );
		if ( ! $order ) {
			return;
		}

		$refund = wc_get_order( $refund_id );
		if ( ! $refund ) {
			return;
		}

		$customer_key = wstl_get_customer_key( $order );

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

		$refund_amount = abs( $refund->get_amount() );
		$order_total = $order->get_total();
		$is_full_refund = $refund_amount >= $order_total;

		// Calculate days since order.
		$order_date = $order->get_date_created();
		$days_since_order = $order_date ? wstl_days_between( $order_date->getTimestamp(), time() ) : 0;

		// Log the typed refund event used by analytics and notifications.
		$this->log_event(
			$customer_key['email_hash'],
			$is_full_refund ? 'full_refund' : 'partial_refund',
			array(
				'order_id'         => $order_id,
				'refund_id'        => $refund_id,
				'refund_amount'    => $refund_amount,
				'order_total'      => $order_total,
				'is_full_refund'   => $is_full_refund,
				'refund_reason'    => $refund->get_reason(),
				'days_since_order' => $days_since_order,
			),
			$order_id
		);

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

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

	/**
	 * Update customer refund stats.
	 *
	 * @since 1.0.0
	 * @param string $email_hash     Customer email hash.
	 * @param float  $refund_amount  Refund amount.
	 * @param bool   $is_full_refund Whether it's a full refund.
	 */
	private function update_customer_stats( string $email_hash, float $refund_amount, bool $is_full_refund ): void {
		global $wpdb;

		$table = $wpdb->prefix . 'trustlens_customers';

		// Increment refund counters and update 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_refunds = total_refunds + 1,
			     total_refund_value = total_refund_value + %f,
			     full_refunds = full_refunds + %d,
			     partial_refunds = partial_refunds + %d,
			     -- total_refunds 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 numerator
			     -- (off-by-one: 5/10=50.00 instead of the correct 4/10=40.00).
			     return_rate = CASE
			         WHEN total_orders > 0 THEN (total_refunds / total_orders) * 100
			         ELSE 0
			     END,
			     last_refund_date = %s,
			     updated_at = %s
			 WHERE email_hash = %s",
			$refund_amount,
			$is_full_refund ? 1 : 0,
			$is_full_refund ? 0 : 1,
			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

		// 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();

		// Get thresholds from settings.
		$high_threshold = (int) get_option( 'trustlens_returns_high_threshold', 40 );
		$critical_threshold = (int) get_option( 'trustlens_returns_critical_threshold', 60 );

		// Return rate scoring.
		$return_rate = (float) $customer->return_rate;

		if ( $return_rate >= $critical_threshold ) {
			$score -= 40;
			$reasons[] = sprintf(
				/* translators: %.0f: return rate percentage */
				__( 'Very high return rate: %.0f%%', 'trustlens' ),
				$return_rate
			);
		} elseif ( $return_rate >= $high_threshold ) {
			$score -= 25;
			$reasons[] = sprintf(
				/* translators: %.0f: return rate percentage */
				__( 'High return rate: %.0f%%', 'trustlens' ),
				$return_rate
			);
		} elseif ( $return_rate >= 25 ) {
			$score -= 10;
			$reasons[] = sprintf(
				/* translators: %.0f: return rate percentage */
				__( 'Elevated return rate: %.0f%%', 'trustlens' ),
				$return_rate
			);
		}

		// Full refund ratio (wardrobing indicator).
		if ( $customer->total_refunds >= 3 ) {
			$full_ratio = $customer->full_refunds / $customer->total_refunds;

			if ( $full_ratio >= 0.9 ) {
				$score -= 10;
				$reasons[] = __( '90%+ full refunds (wardrobing risk)', 'trustlens' );
			}
		}

		// High refund value.
		$refund_value = (float) $customer->total_refund_value;

		if ( $refund_value >= 2000 ) {
			$score -= 10;
			$reasons[] = sprintf(
				/* translators: %s: formatted currency value */
				__( 'High refund value: %s', 'trustlens' ),
				wp_strip_all_tags( wc_price( $refund_value ) )
			);
		} elseif ( $refund_value >= 1000 ) {
			$score -= 5;
		}

		// Positive: Excellent return history.
		if ( $customer->total_orders >= 5 && $return_rate <= 5 ) {
			$score += 10;
			$reasons[] = __( 'Excellent return history', 'trustlens' );
		}

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

	// Thresholds (high/critical) are configured in Settings > General, not via get_settings_fields().
}
