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

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

/**
 * Class implementation.
 */
class Noesia_CS_Passport_Service {
	const META_TOKEN        = '_noesia_cs_care_token';
	const META_TOKEN_HASH   = '_noesia_cs_care_token_hash';
	const META_TOKEN_DATE   = '_noesia_cs_care_token_date';
	const META_TOKEN_STATUS = '_noesia_cs_care_token_status';
	/**
	 * Runtime dependency or state value.
	 *
	 * @var mixed
	 */
	private $order_repository;

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order_repository Order repository.
	 */
	public function __construct( Noesia_CS_Order_Repository $order_repository = null ) {
		$this->order_repository = $order_repository ? $order_repository : new Noesia_CS_Order_Repository();
	}


	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $limit Limit.
	 */
	public function get_recent_orders( $limit = 12 ) {
		return $this->order_repository->get_recent_orders( $limit );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function get_existing_token_for_order( $order ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
			return '';
		}

		$token   = (string) $order->get_meta( self::META_TOKEN, true );
		$status  = (string) $order->get_meta( self::META_TOKEN_STATUS, true );

		if ( $token && 'revoked' !== $status && $this->is_valid_token_format( $token ) ) {
			$this->refresh_token_hash_if_needed( $order, $token );
			return $token;
		}

		return '';
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function order_has_active_token( $order ) {
		return '' !== $this->get_existing_token_for_order( $order );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function get_or_create_token_for_order( $order ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
			return '';
		}

		$existing = $this->get_existing_token_for_order( $order );
		if ( $existing ) {
			return $existing;
		}

		return $this->regenerate_token_for_order( $order );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function regenerate_token_for_order( $order ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
			return '';
		}

		$token = $this->generate_token();
		$order->update_meta_data( self::META_TOKEN, $token );
		$order->update_meta_data( self::META_TOKEN_HASH, $this->hash_token( $token ) );
		$order->update_meta_data( self::META_TOKEN_DATE, time() );
		$order->update_meta_data( self::META_TOKEN_STATUS, 'active' );
		$order->save();
		delete_transient( 'noesia_cs_dashboard_stats_v1' );
		foreach ( array( 7, 30, 90, 365 ) as $noesia_cs_range ) {
			delete_transient( 'noesia_cs_dashboard_stats_v2_' . $noesia_cs_range );
		}

		return $token;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function get_care_url_for_order( $order ) {
		$token = $this->get_or_create_token_for_order( $order );
		if ( ! $token ) {
			return '';
		}
		return home_url( user_trailingslashit( 'noesia-care/' . rawurlencode( $token ) ) );
	}



	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function get_existing_care_url_for_order( $order ) {
		$token = $this->get_existing_token_for_order( $order );
		if ( ! $token ) {
			return '';
		}
		return home_url( user_trailingslashit( 'noesia-care/' . rawurlencode( $token ) ) );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $token Token.
	 */
	public function find_order_by_token( $token ) {
		if ( ! $this->order_repository->is_available() ) {
			return null;
		}

		$token = sanitize_text_field( $token );
		if ( ! $this->is_valid_token_format( $token ) ) {
			return null;
		}

		$current_hash = $this->hash_token( $token );
		$order        = $this->order_repository->find_order_by_token_hash( self::META_TOKEN_HASH, $current_hash );

		if ( ! $order ) {
			$order = $this->order_repository->find_order_by_meta_value( self::META_TOKEN, $token, 'Raw token fallback lookup' );
		}

		if ( ! $order ) {
			return null;
		}

		$status = (string) $order->get_meta( self::META_TOKEN_STATUS, true );
		$stored = (string) $order->get_meta( self::META_TOKEN, true );

		if ( 'revoked' === $status || ! hash_equals( $stored, $token ) ) {
			return null;
		}

		$this->refresh_token_hash_if_needed( $order, $token, $current_hash );

		return $order;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function get_safe_order_reference( $order ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
			return '';
		}
		return '#' . $order->get_order_number();
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $order Order.
	 */
	public function get_warranty_status( $order ) {
		$warranty_service = class_exists( 'Noesia_CS_Warranty_Service' ) ? new Noesia_CS_Warranty_Service() : null;
		if ( $warranty_service ) {
			return $warranty_service->get_order_warranty_summary( $order );
		}

		return array(
			'label'   => Noesia_CS_Settings::get( 'warranty_unknown_text', __( 'Warranty not configured', 'noesia-commerce-suite' ) ),
			'state'   => 'neutral',
			'expiry'  => '',
		);
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $item Item.
	 */
	public function get_reorder_url_for_item( $item ) {
		if ( ! $item || ! method_exists( $item, 'get_product' ) ) {
			return '';
		}
		$product = $item->get_product();
		if ( ! $product ) {
			return '';
		}

		$behavior = Noesia_CS_Settings::get( 'reorder_button_behavior', 'product' );
		if ( 'cart' === $behavior ) {
			return add_query_arg( 'add-to-cart', absint( $product->get_id() ), wc_get_cart_url() );
		}
		return get_permalink( $product->get_id() );
	}

	/**
	 * Handles the related plugin operation.
	 */
	private function generate_token() {
		try {
			return bin2hex( random_bytes( 16 ) );
		} catch ( Exception $exception ) {
			return wp_generate_password( 32, false, false );
		}
	}

	/**
	 * Refreshes the stored token hash when WordPress salts have changed.
	 *
	 * @param mixed  $order Order.
	 * @param string $token Token.
	 * @param string $current_hash Current token hash.
	 */
	private function refresh_token_hash_if_needed( $order, $token, $current_hash = '' ) {
		if ( ! $order || ! is_a( $order, 'WC_Order' ) || ! $this->is_valid_token_format( $token ) ) {
			return;
		}

		$current_hash = $current_hash ? $current_hash : $this->hash_token( $token );
		$stored_hash  = (string) $order->get_meta( self::META_TOKEN_HASH, true );

		if ( hash_equals( $stored_hash, $current_hash ) ) {
			return;
		}

		$order->update_meta_data( self::META_TOKEN_HASH, $current_hash );
		$order->save();
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $token Token.
	 */
	private function hash_token( $token ) {
		return hash( 'sha256', $token );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $token Token.
	 */
	private function is_valid_token_format( $token ) {
		return is_string( $token ) && (bool) preg_match( '/^[a-zA-Z0-9]{32,96}$/', $token );
	}
}
