<?php
/**
 * Frontend data retrieval service for DataStream.
 *
 * @package DataStream
 */

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

/**
 * Class DataStream_Provider
 */
class DataStream_Provider {

	/**
	 * DAO instance.
	 *
	 * @var DataStream_DAO|null
	 */
	private static $dao = null;

	/**
	 * Lazy-init DAO.
	 *
	 * @return DataStream_DAO
	 */
	private static function dao() {
		if ( null === self::$dao ) {
			self::$dao = new DataStream_DAO();
		}

		return self::$dao;
	}

	/**
	 * Build transient cache key for an external ID.
	 *
	 * @param string $external_id External identifier.
	 * @return string
	 */
	private static function cache_key( $external_id ) {
		return 'ds_cache_' . md5( sanitize_text_field( $external_id ) );
	}

	/**
	 * Retrieve cache TTL in seconds.
	 *
	 * @return int
	 */
	private static function cache_ttl() {
		$ttl = absint( DataStream_Config::get( 'cache_ttl' ) );
		return max( 60, min( DAY_IN_SECONDS, $ttl ) );
	}

	/**
	 * Retrieve a specific dataset by ID with transient caching.
	 *
	 * @param string $external_id The unique identifier from the source API.
	 * @return array<string, mixed>|null
	 */
	public static function get_data( $external_id ) {
		$external_id = sanitize_text_field( $external_id );

		if ( '' === $external_id ) {
			return null;
		}

		$cache_key   = self::cache_key( $external_id );
		$cached_data = get_transient( $cache_key );

		if ( false !== $cached_data && is_array( $cached_data ) ) {
			return $cached_data;
		}

		$result = self::dao()->get_payload_by_external_id( $external_id );

		if ( ! $result ) {
			return null;
		}

		$data = json_decode( $result, true );

		if ( ! is_array( $data ) ) {
			return null;
		}

		set_transient( $cache_key, $data, self::cache_ttl() );

		return $data;
	}

	/**
	 * Invalidate cached data for an external ID.
	 *
	 * @param string $external_id External identifier.
	 */
	public static function invalidate_cache( $external_id ) {
		delete_transient( self::cache_key( $external_id ) );
	}

	/**
	 * Clear all DataStream transients.
	 *
	 * @return int Number of deleted transients.
	 */
	public static function flush_all_caches() {
		global $wpdb;

		$like   = $wpdb->esc_like( '_transient_ds_cache_' ) . '%';
		$count  = 0;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- prefix scan of our own transients; WP has no API for that.
		$rows   = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
				$like
			)
		);

		foreach ( $rows as $option_name ) {
			$key = str_replace( '_transient_', '', $option_name );
			delete_transient( $key );
			++$count;
		}

		return $count;
	}
}
