<?php
/**
 * PA-API request payload construction
 *
 * Builds SearchItems payloads from normalized search parameters.
 * Uses OffersV2 exclusively.
 */

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

/**
 * Get the offer resources for PA-API v5 requests (PascalCase).
 *
 * Uses OffersV2 exclusively - V1 has been deprecated.
 *
 * @return array Resource identifiers for PA-API request
 */
function psfa_get_offer_resources(): array {
    // Base resources (always included)
    $resources = array(
        'Images.Primary.Large',
        'ItemInfo.Title',
        'ItemInfo.ByLineInfo',
        'ItemInfo.Features',
        'CustomerReviews.StarRating',
        'CustomerReviews.Count',
        'BrowseNodeInfo.WebsiteSalesRank',
        'SearchRefinements',
    );

    // OffersV2 resources (full V2 - no V1 fallback)
    // Note: DeliveryInfo and ProgramEligibility are V1 Offers resources only,
    // NOT valid on OffersV2 (causes 400 error on both PA-API v5 and Creators API).
    $v2_resources = array(
        'OffersV2.Listings.Price',
        'OffersV2.Listings.Condition',
        'OffersV2.Listings.MerchantInfo',
        'OffersV2.Listings.Availability',
        'OffersV2.Listings.DealDetails',
        'OffersV2.Listings.IsBuyBoxWinner',
        'OffersV2.Listings.LoyaltyPoints',
    );

    return array_merge($resources, $v2_resources);
}

/**
 * Get the offer resources for Creators API requests (camelCase).
 *
 * Creators API uses camelCase resource names instead of PascalCase.
 *
 * @return array Resource identifiers for Creators API request
 */
function psfa_get_creators_api_resources(): array {
    return array(
        'images.primary.large',
        'images.primary.small',
        'itemInfo.title',
        'itemInfo.byLineInfo',
        'itemInfo.features',
        'browseNodeInfo.websiteSalesRank',
        'searchRefinements',
        'offersV2.listings.price',
        'offersV2.listings.condition',
        'offersV2.listings.merchantInfo',
        'offersV2.listings.availability',
        'offersV2.listings.dealDetails',
        'offersV2.listings.isBuyBoxWinner',
        // Note: deliveryInfo and programEligibility are NOT valid Creators API resources
        // (only available on AWSSig4 PA-API v5). isPrime/isPrimeExclusive unavailable on OAuth.
        'customerReviews.starRating',
        'customerReviews.count',
    );
}

/**
 * Get the resources for Creators API GetItems requests (camelCase).
 *
 * GetItems doesn't support searchRefinements but does support images.variants.
 *
 * @return array Resource identifiers for Creators API GetItems request
 */
function psfa_get_creators_api_getitems_resources(): array {
    return array(
        'images.primary.large',
        'images.primary.small',
        'images.variants.large',
        'itemInfo.title',
        'itemInfo.byLineInfo',
        'itemInfo.features',
        'browseNodeInfo.websiteSalesRank',
        'offersV2.listings.price',
        'offersV2.listings.condition',
        'offersV2.listings.merchantInfo',
        'offersV2.listings.availability',
        'offersV2.listings.dealDetails',
        'offersV2.listings.isBuyBoxWinner',
        // Note: deliveryInfo and programEligibility are NOT valid Creators API resources
        'customerReviews.starRating',
        'customerReviews.count',
    );
}

/**
 * Build the PA-API SearchItems payload from normalized inputs.
 *
 * This keeps the logic for SearchIndex/Keywords/SortBy/filters in one place.
 *
 * @param array $params {
 *   @type string $search_term
 *   @type string $category
 *   @type float  $price_min
 *   @type float  $price_max
 *   @type int    $page
 *   @type string $sort
 *   @type string $brand
 *   @type string $condition
 *   @type string $merchant
 * }
 * @param string $associate_tag
 * @return array
 */
function psfa_build_search_payload(array $params, $associate_tag) {
    $search_term        = $params['search_term'] ?? '';
    $category           = $params['category'] ?? '';
    $price_min          = (float) ($params['price_min'] ?? 0);
    $price_max          = (float) ($params['price_max'] ?? 0);
    $page               = (int)   ($params['page'] ?? 1);
    $sort               = (string)($params['sort'] ?? '');
    $brand              = (string)($params['brand'] ?? '');
    $condition          = (string)($params['condition'] ?? '');
    $merchant           = (string)($params['merchant'] ?? '');
    $availability       = (string)($params['availability'] ?? '');
    // Premium filters
    $has_deal           = (string)($params['has_deal'] ?? '');
    $min_rating         = (int)   ($params['min_rating'] ?? 0);
    $min_saving_percent = (int)   ($params['min_saving_percent'] ?? 0);

    // Map category names to valid Amazon SearchIndex values.
    $search_index_map = array(
        'Electronics'   => 'Electronics',
        'Books'         => 'Books',
        'Fashion'       => 'Apparel',
        'ToysAndGames'  => 'ToysAndGames',
        'HomeGarden'    => 'HomeGarden',
        'TodaysDeals'   => 'All', // Today's Deals searches across all categories
    );

    $search_index = 'All';
    if (!empty($category) && $category !== 'All') {
        $search_index = $search_index_map[$category] ?? $category;
    }

    // If no search term but category is provided, use category-specific keywords.
    $keywords = $search_term;
    if (empty($keywords) && !empty($category) && $category !== 'All') {
        $category_keywords = array(
            'Electronics'  => 'electronics',
            'Books'        => 'books',
            'Fashion'      => 'clothing',
            'ToysAndGames' => 'toys',
            'HomeGarden'   => 'home',
            'TodaysDeals'  => 'deals', // Search for deals across all categories
        );
        $keywords = $category_keywords[$category] ?? 'products';
    }

    if (empty($keywords)) {
        // psfa_amazon_search_products() expects to see this error string when
        // keywords are missing; keep the same behaviour.
        return array(
            'error' => 'Search query or category required. Keywords cannot be empty.',
        );
    }

    $payload = array(
        'Keywords'     => $keywords,
        'SearchIndex'  => $search_index,
        'PartnerTag'   => $associate_tag,
        'PartnerType'  => 'Associates',
        'ItemCount'    => 10,
        'ItemPage'     => $page,
        'Resources'    => psfa_get_offer_resources(),
    );

    // Brand filter.
    if ($brand !== '') {
        $payload['Brand'] = $brand;
    }

    // SortBy rules (same logic as before, just centralised here).
    $price_sorts   = array('Price:LowToHigh', 'Price:HighToLow');
    $is_price_sort = in_array($sort, $price_sorts, true);

    if ($sort !== '') {
        if ($is_price_sort && ($price_min > 0 || $price_max > 0)) {
            // Price sort + price filter: skip server-side, will sort client-side after filtering.
            // Still include SortBy so the cache key differentiates between sort options.
            $payload['SortBy'] = $sort;
        } else {
            $valid_sorts = array(
                'Relevance',
                'Price:LowToHigh',
                'Price:HighToLow',
                'NewestArrivals',
                'AvgCustomerReviews',
                'Featured',
            );
            if (in_array($sort, $valid_sorts, true)) {
                $payload['SortBy'] = $sort;
            }
        }
    }

    // Condition filter (ignore 'All').
    if ($condition !== '' && in_array($condition, array('New', 'Used', 'Refurbished', 'Collectible'), true)) {
        $payload['Condition'] = $condition;
    }

    // Merchant filter.
    if ($merchant !== '' && in_array($merchant, array('Amazon', 'All'), true)) {
        $payload['Merchant'] = $merchant;
    }

    // Availability filter
    // 'Available' = in stock only (default), 'IncludeOutOfStock' = all items
    if ($availability === 'IncludeOutOfStock' || $availability === 'OutOfStockOnly') {
        // OutOfStockOnly requires IncludeOutOfStock from PA-API, then client-side filtering
        $payload['Availability'] = 'IncludeOutOfStock';
    } elseif ($availability === 'Available') {
        $payload['Availability'] = 'Available';
    }
    // Note: If empty, PA-API defaults to 'Available'

    

    // MinPrice/MaxPrice - Creators API supports these, PA-API v5 does not
    // Prices are in lowest currency denomination (e.g., cents for USD)
    // Only add if using OAuth auth type (checked in OAuth client)
    if ($price_min > 0) {
        $payload['MinPrice'] = (int) ($price_min * 100); // Convert dollars to cents
    }
    if ($price_max > 0) {
        $payload['MaxPrice'] = (int) ($price_max * 100); // Convert dollars to cents
    }

    return $payload;
}

