<?php
/**
 * Unified product cache.
 *
 * Provides a single cache layer for individual product data (per ASIN).
 *
 * @package PSFA
 * @since   2.11.0
 */

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

/**
 * Get a single cached product by ASIN.
 *
 * @param string $asin Product ASIN.
 * @return array|null Product data array or null on miss.
 */
function psfa_get_cached_product( string $asin ): ?array {
    $cached = get_transient( 'psfa_product_' . $asin );

    if ( false !== $cached && is_array( $cached ) ) {
        // Strip internal metadata before returning to consumers.
        unset( $cached['_psfa_created_at'] );
        return $cached;
    }

    return null;
}

/**
 * Store a product in the unified cache.
 *
 * @param string $asin Product ASIN.
 * @param array  $data Product data array.
 * @return void
 */
function psfa_set_cached_product( string $asin, array $data ): void {
    $data['_psfa_created_at'] = time();
    set_transient( 'psfa_product_' . $asin, $data, HOUR_IN_SECONDS );
}

/**
 * Batch-get cached products for multiple ASINs.
 *
 * @param array $asins Array of ASIN strings.
 * @return array Associative array keyed by ASIN (only cached hits included).
 */
function psfa_get_cached_products( array $asins ): array {
    $results = array();
    foreach ( $asins as $asin ) {
        $product = psfa_get_cached_product( $asin );
        if ( null !== $product ) {
            $results[ $asin ] = $product;
        }
    }
    return $results;
}

/**
 * Clear product cache.
 *
 * @param string|null $asin Specific ASIN to clear, or null to clear all.
 * @return int Number of transients deleted.
 */
function psfa_clear_product_cache( ?string $asin = null ): int {
    if ( null !== $asin ) {
        return delete_transient( 'psfa_product_' . $asin ) ? 1 : 0;
    }

    // Clear all product transients.
    // In a real WP environment this uses $wpdb; in tests we iterate the transient store.
    global $wpdb, $psfa_test_transients;

    $count = 0;

    if ( isset( $psfa_test_transients ) && is_array( $psfa_test_transients ) ) {
        // Test environment: iterate in-memory store.
        foreach ( array_keys( $psfa_test_transients ) as $key ) {
            if ( 0 === strpos( $key, 'psfa_product_' ) ) {
                unset( $psfa_test_transients[ $key ] );
                ++$count;
            }
        }
        return $count;
    }

    // Production environment: bulk delete via SQL.
    if ( isset( $wpdb ) ) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $count = (int) $wpdb->query(
            "DELETE FROM {$wpdb->options}
             WHERE option_name LIKE '_transient_psfa_product_%'
                OR option_name LIKE '_transient_timeout_psfa_product_%'"
        );
        // Each transient has 2 rows (value + timeout), so real count is roughly half.
        $count = (int) floor( $count / 2 );
    }

    return $count;
}
