<?php
/**
 * Class Noesia Cs Care Action Service.
 *
 * @package Noesia_Commerce_Suite
 */

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

/**
 * Class implementation.
 */
class Noesia_CS_Care_Action_Service {
	const LOG_OPTION = 'noesia_cs_care_action_logs';
	const MAX_LOGS   = 1200;

	/**
	 * Handles the related plugin operation.
	 */
	public function is_enabled() {
		return 'yes' === Noesia_CS_Settings::get( 'care_action_tracking_enabled', 'yes' );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function get_action_labels() {
		return array(
			'support'            => __( 'Support', 'noesia-commerce-suite' ),
			'reorder'            => __( 'Reorder', 'noesia-commerce-suite' ),
			'review_google'      => __( 'Google Review', 'noesia-commerce-suite' ),
			'review_trustpilot'  => __( 'Trustpilot Review', 'noesia-commerce-suite' ),
			'review_store'       => __( 'Store Review', 'noesia-commerce-suite' ),
		);
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $action Action.
	 */
	public function is_valid_action( $action ) {
		$action = sanitize_key( $action );
		return array_key_exists( $action, $this->get_action_labels() );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 * @param mixed $action Action.
	 * @param mixed $args Args.
	 */
	public function get_action_url( $order, $action, $args = array() ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) || ! $this->is_valid_action( $action ) ) {
			return '';
		}

		$token = (string) $order->get_meta( Noesia_CS_Passport_Service::META_TOKEN, true );
		if ( ! $token ) {
			return '';
		}

		$url = home_url( user_trailingslashit( 'noesia-care-action/' . rawurlencode( $token ) . '/' . sanitize_key( $action ) ) );
		if ( ! empty( $args ) && is_array( $args ) ) {
			$clean_args = array();
			if ( isset( $args['item_id'] ) ) {
				$clean_args['item_id'] = absint( $args['item_id'] );
			}
			if ( $clean_args ) {
				$url = add_query_arg( $clean_args, $url );
			}
		}

		return $url;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 * @param mixed $action Action.
	 * @param mixed $context Context.
	 */
	public function record_action( $order, $action, $context = array() ) {
		if ( ! $this->is_enabled() || ! $order || ! is_a( $order, 'WC_Order' ) || ! $this->is_valid_action( $action ) ) {
			return false;
		}

		$logs = get_option( self::LOG_OPTION, array() );
		if ( ! is_array( $logs ) ) {
			$logs = array();
		}

		$entry = array(
			'time'        => time(),
			'order_id'    => absint( $order->get_id() ),
			'action'      => sanitize_key( $action ),
			'item_id'     => isset( $context['item_id'] ) ? absint( $context['item_id'] ) : 0,
			'product_id'  => isset( $context['product_id'] ) ? absint( $context['product_id'] ) : 0,
			'source'      => isset( $context['source'] ) ? sanitize_key( $context['source'] ) : 'care_page',
		);

		$logs[] = $entry;
		if ( count( $logs ) > self::MAX_LOGS ) {
			$logs = array_slice( $logs, -1 * self::MAX_LOGS );
		}

		update_option( self::LOG_OPTION, $logs, false );
		delete_transient( 'noesia_cs_care_action_summary_v1' );
		$this->delete_range_summary_transients();

		return true;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $start_time Start time.
	 * @param mixed $end_time End time.
	 */
	public function get_summary( $start_time = 0, $end_time = 0 ) {
		$start_time  = absint( $start_time );
		$end_time    = absint( $end_time );
		$cache_key   = $start_time && $end_time ? 'noesia_cs_care_action_summary_v2_' . md5( $start_time . '|' . $end_time ) : 'noesia_cs_care_action_summary_v1';
		$cached      = get_transient( $cache_key );
		if ( is_array( $cached ) ) {
			return $cached;
		}

		$labels = $this->get_action_labels();
		$summary = array(
			'enabled'         => $this->is_enabled(),
			'total'           => 0,
			'last_30_days'    => 0,
			'range_count'     => 0,
			'by_action'       => array(),
			'recent'          => array(),
			'retains_no_pii'  => true,
		);

		foreach ( $labels as $key => $label ) {
			$summary['by_action'][ $key ] = array(
				'label'  => $label,
				'count'  => 0,
			);
		}

		$logs = get_option( self::LOG_OPTION, array() );
		if ( ! is_array( $logs ) ) {
			$logs = array();
		}

		$cutoff = time() - ( 30 * DAY_IN_SECONDS );
		foreach ( $logs as $entry ) {
			if ( ! is_array( $entry ) ) {
				continue;
			}
			$action  = isset( $entry['action'] ) ? sanitize_key( $entry['action'] ) : '';
			$time    = isset( $entry['time'] ) ? absint( $entry['time'] ) : 0;
			if ( ! isset( $summary['by_action'][ $action ] ) ) {
				continue;
			}
			$summary['total']++;
			$summary['by_action'][ $action ]['count']++;
			if ( $time >= $cutoff ) {
				$summary['last_30_days']++;
			}
			if ( $start_time && $end_time && $time >= $start_time && $time <= $end_time ) {
				$summary['range_count']++;
			}
		}

		$recent = array_slice( array_reverse( $logs ), 0, 8 );
		foreach ( $recent as $entry ) {
			if ( ! is_array( $entry ) ) {
				continue;
			}
			$action = isset( $entry['action'] ) ? sanitize_key( $entry['action'] ) : '';
			if ( ! isset( $labels[ $action ] ) ) {
				continue;
			}
			$summary['recent'][] = array(
				'time'      => isset( $entry['time'] ) ? absint( $entry['time'] ) : 0,
				'order_id'  => isset( $entry['order_id'] ) ? absint( $entry['order_id'] ) : 0,
				'action'    => $action,
				'label'     => $labels[ $action ],
			);
		}

		set_transient( $cache_key, $summary, 5 * MINUTE_IN_SECONDS );
		return $summary;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $cutoff Cutoff.
	 */
	public function prune_logs( $cutoff ) {
		$logs = get_option( self::LOG_OPTION, array() );
		if ( ! is_array( $logs ) ) {
			return 0;
		}

		$before = count( $logs );
		$logs = array_values(
			array_filter(
				$logs,
				function ( $entry ) use ( $cutoff ) {
					$time = is_array( $entry ) && isset( $entry['time'] ) ? absint( $entry['time'] ) : 0;
					return ! $time || $time >= $cutoff;
				}
			)
		);
		update_option( self::LOG_OPTION, $logs, false );
		delete_transient( 'noesia_cs_care_action_summary_v1' );
		$this->delete_range_summary_transients();

		return max( 0, $before - count( $logs ) );
	}
	/**
	 * Handles the related plugin operation.
	 */
	private function delete_range_summary_transients() {
		global $wpdb;
		if ( ! isset( $wpdb ) ) {
			return;
		}
		$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_noesia_cs_care_action_summary_v2_%' OR option_name LIKE '_transient_timeout_noesia_cs_care_action_summary_v2_%'" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	}

}
