<?php

namespace WPKIN_SHOP_MANAGER\Modules;

if ( ! defined( 'ABSPATH' ) ) {
	wp_die( esc_html__( 'You can\'t access this page', 'shop-manager' ) );
}

/**
 * Rule-based insight engine for the dashboard.
 * No external API calls — all logic based on local WooCommerce data.
 */
class InsightEngine {

	const TRANSIENT_KEY = 'wpkin_sm_insights_v3';
	const TRANSIENT_TTL = 15 * MINUTE_IN_SECONDS;

	/**
	 * Return top-6 insights sorted by severity, with dismissed ones removed.
	 */
	public static function get_insights(): array {
		$cached = get_transient( self::TRANSIENT_KEY );
		if ( false === $cached ) {
			$cached = array_merge(
				self::check_pending_orders(),
				self::check_long_processing(),
				self::check_low_stock(),
				self::check_refund_spike(),
				self::check_revenue_drop(),
				self::check_unread_reviews()
			);
			usort( $cached, fn( $a, $b ) => $b['severity_score'] <=> $a['severity_score'] );
			$cached = array_slice( $cached, 0, 6 );
			set_transient( self::TRANSIENT_KEY, $cached, self::TRANSIENT_TTL );
		}

		// Filter dismissed insights for current user
		$user_id   = get_current_user_id();
		$dismissed = get_user_meta( $user_id, '_sm_dismissed_insights', true );
		$dismissed = is_array( $dismissed ) ? $dismissed : [];
		$now       = time();

		// Clean up expired dismissals
		$dismissed = array_filter( $dismissed, fn( $d ) => $d['dismissed_until'] > $now );

		$dismissed_ids = array_column( $dismissed, 'id' );
		return array_values( array_filter( $cached, fn( $i ) => ! in_array( $i['id'], $dismissed_ids, true ) ) );
	}

	/**
	 * Dismiss an insight for 24 hours.
	 */
	public static function dismiss( string $insight_id ): void {
		$user_id   = get_current_user_id();
		$dismissed = get_user_meta( $user_id, '_sm_dismissed_insights', true );
		$dismissed = is_array( $dismissed ) ? $dismissed : [];
		$now       = time();

		// Remove expired + same id
		$dismissed = array_filter( $dismissed, fn( $d ) => $d['dismissed_until'] > $now && $d['id'] !== $insight_id );
		$dismissed[] = [
			'id'              => $insight_id,
			'dismissed_until' => $now + DAY_IN_SECONDS,
		];

		update_user_meta( $user_id, '_sm_dismissed_insights', array_values( $dismissed ) );
	}

	/**
	 * Clear transient when orders change.
	 */
	public static function clear_cache(): void {
		delete_transient( self::TRANSIENT_KEY );
	}

	// ─────────────────────────────────────────────────────────────────────────
	// Detectors
	// ─────────────────────────────────────────────────────────────────────────

	private static function check_pending_orders(): array {
		$two_hours_ago = gmdate( 'Y-m-d H:i:s', time() - 2 * HOUR_IN_SECONDS );
		$orders = wc_get_orders( [
			'status'      => 'pending',
			'date_before' => $two_hours_ago,
			'limit'       => -1,
			'return'      => 'ids',
		] );
		$count = count( $orders );
		if ( $count === 0 ) {
			return [];
		}

		if ( $count > 5 ) {
			$type  = 'error';
			$score = 90;
		} elseif ( $count > 2 ) {
			$type  = 'warning';
			$score = 70;
		} else {
			$type  = 'info';
			$score = 40;
		}

		return [ [
			'id'             => 'pending_orders',
			'type'           => $type,
			'icon'           => '⏳',
			'title'          => __( 'Pending Orders', 'shop-manager' ),
			'message'        => sprintf(
				/* translators: %d: number of pending orders */
				_n( '%d order has been pending for more than 2 hours.', '%d orders have been pending for more than 2 hours.', $count, 'shop-manager' ),
				$count
			),
			'action'         => [
				'label' => __( 'View', 'shop-manager' ),
				'url'   => '/sm-dashboard/orders/pending',
			],
			'severity_score' => $score,
			'generated_at'   => current_time( 'c' ),
		] ];
	}

	private static function check_long_processing(): array {
		$day_ago = gmdate( 'Y-m-d H:i:s', time() - DAY_IN_SECONDS );
		$orders  = wc_get_orders( [
			'status'      => 'processing',
			'date_before' => $day_ago,
			'limit'       => -1,
			'return'      => 'ids',
		] );
		$count = count( $orders );
		if ( $count === 0 ) {
			return [];
		}

		return [ [
			'id'             => 'long_processing',
			'type'           => 'warning',
			'icon'           => '🔄',
			'title'          => __( 'Long Processing Orders', 'shop-manager' ),
			'message'        => sprintf(
				_n( '%d order has been in processing for over 24 hours.', '%d orders have been in processing for over 24 hours.', $count, 'shop-manager' ),
				$count
			),
			'action'         => [
				'label' => __( 'View', 'shop-manager' ),
				'url'   => '/sm-dashboard/orders/processing',
			],
			'severity_score' => 75,
			'generated_at'   => current_time( 'c' ),
		] ];
	}

	private static function check_low_stock(): array {
		$threshold = (int) get_option( 'woocommerce_notify_low_stock_amount', 5 );

		$args = [
			'post_type'      => 'product',
			'post_status'    => 'publish',
			'posts_per_page' => -1,
			'fields'         => 'ids',
			'meta_query'     => [
				'relation' => 'AND',
				[
					'key'     => '_manage_stock',
					'value'   => 'yes',
					'compare' => '=',
				],
				[
					'key'     => '_stock',
					'value'   => $threshold,
					'compare' => '<=',
					'type'    => 'NUMERIC',
				],
				[
					'key'     => '_stock',
					'value'   => 0,
					'compare' => '>',
					'type'    => 'NUMERIC',
				],
			],
		];

		$query = new \WP_Query( $args );
		$count = $query->found_posts;

		if ( $count === 0 ) {
			return [];
		}

		return [ [
			'id'             => 'low_stock',
			'type'           => 'warning',
			'icon'           => '📦',
			'title'          => __( 'Low Stock Alert', 'shop-manager' ),
			'message'        => sprintf(
				_n( '%d product is running low on stock.', '%d products are running low on stock.', $count, 'shop-manager' ),
				$count
			),
			'action'         => [
				'label' => __( 'View Products', 'shop-manager' ),
				'url'   => '/sm-dashboard/products/all?low_stock=yes',
			],
			'severity_score' => 65,
			'generated_at'   => current_time( 'c' ),
		] ];
	}

	private static function check_refund_spike(): array {
		$week_start      = gmdate( 'Y-m-d', strtotime( 'monday this week' ) );
		$last_week_start = gmdate( 'Y-m-d', strtotime( 'monday last week' ) );
		$last_week_end   = gmdate( 'Y-m-d', strtotime( 'sunday last week' ) );

		$this_week_refunds = count( wc_get_orders( [
			'status'       => 'refunded',
			'date_created' => $week_start . '...' . gmdate( 'Y-m-d' ),
			'limit'        => -1,
			'return'       => 'ids',
		] ) );

		$last_week_refunds = count( wc_get_orders( [
			'status'       => 'refunded',
			'date_created' => $last_week_start . '...' . $last_week_end,
			'limit'        => -1,
			'return'       => 'ids',
		] ) );

		if ( $this_week_refunds === 0 ) {
			return [];
		}
		if ( $last_week_refunds > 0 && $this_week_refunds <= $last_week_refunds * 1.5 ) {
			return [];
		}

		return [ [
			'id'             => 'refund_spike',
			'type'           => 'warning',
			'icon'           => '↩️',
			'title'          => __( 'Refund Spike', 'shop-manager' ),
			'message'        => sprintf(
				__( '%d refunds this week — up %.0f%% from last week.', 'shop-manager' ),
				$this_week_refunds,
				$last_week_refunds > 0 ? ( ( $this_week_refunds - $last_week_refunds ) / $last_week_refunds * 100 ) : 100
			),
			'action'         => [
				'label' => __( 'View Refunds', 'shop-manager' ),
				'url'   => '/sm-dashboard/orders/refunded',
			],
			'severity_score' => 60,
			'generated_at'   => current_time( 'c' ),
		] ];
	}

	private static function check_revenue_drop(): array {
		$today     = gmdate( 'Y-m-d' );
		$yesterday = gmdate( 'Y-m-d', strtotime( '-1 day' ) );

		// Revenue today so far
		$today_orders = wc_get_orders( [
			'status'       => [ 'wc-completed', 'wc-processing' ],
			'date_created' => $today . '...' . $today,
			'limit'        => -1,
			'return'       => 'objects',
		] );
		$today_revenue = array_sum( array_map( fn( $o ) => (float) $o->get_total(), $today_orders ) );

		// Revenue same time yesterday
		$yesterday_orders = wc_get_orders( [
			'status'       => [ 'wc-completed', 'wc-processing' ],
			'date_created' => $yesterday . '...' . $yesterday,
			'limit'        => -1,
			'return'       => 'objects',
		] );
		$yesterday_revenue = array_sum( array_map( fn( $o ) => (float) $o->get_total(), $yesterday_orders ) );

		if ( $yesterday_revenue <= 0 || $today_revenue >= $yesterday_revenue * 0.6 ) {
			return [];
		}

		$drop_pct = (int) round( ( 1 - $today_revenue / $yesterday_revenue ) * 100 );

		return [ [
			'id'             => 'revenue_drop',
			'type'           => 'info',
			'icon'           => '📉',
			'title'          => __( 'Revenue Drop', 'shop-manager' ),
			'message'        => sprintf(
				__( "Today's revenue is %d%% lower than yesterday so far.", 'shop-manager' ),
				$drop_pct
			),
			'action'         => null,
			'severity_score' => 50,
			'generated_at'   => current_time( 'c' ),
		] ];
	}

	private static function check_unread_reviews(): array {
		$count = (int) get_comments( [
			'status' => 'hold',
			'type'   => 'review',
			'count'  => true,
		] );

		if ( $count === 0 ) {
			return [];
		}

		return [ [
			'id'             => 'unread_reviews',
			'type'           => 'info',
			'icon'           => '⭐',
			'title'          => __( 'Pending Reviews', 'shop-manager' ),
			'message'        => sprintf(
				_n( '%d review is awaiting approval.', '%d reviews are awaiting approval.', $count, 'shop-manager' ),
				$count
			),
			'action'         => [
				'label' => __( 'View Reviews', 'shop-manager' ),
				'url'   => '/sm-dashboard/reviews',
			],
			'severity_score' => 30,
			'generated_at'   => current_time( 'c' ),
		] ];
	}
}
