<?php
/**
 * Response Normalizer Trait
 *
 * Provides access to offer data from API responses.
 * Supports both OffersV2 (Creators API / OAuth) and legacy Offers (PA-API / AWS Sig V4).
 */

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

trait PSFA_Response_Normalizer {

    /**
     * Get primary listing from item (supports OffersV2 and legacy Offers)
     *
     * @param array $item API item
     * @return array|null Listing data or null
     */
    public function get_listing(array $item): ?array {
        // OffersV2 path (Creators API / OAuth)
        if (isset($item['OffersV2']['Listings'][0])) {
            return $item['OffersV2']['Listings'][0];
        }
        // Legacy Offers path (PA-API / AWS Sig V4)
        if (isset($item['Offers']['Listings'][0])) {
            return $item['Offers']['Listings'][0];
        }
        return null;
    }

    /**
     * Check if item uses OffersV2 format
     *
     * @param array $item API item
     * @return bool True if OffersV2 format
     */
    protected function is_offers_v2(array $item): bool {
        return isset($item['OffersV2']['Listings'][0]);
    }

    /**
     * Get all listings from item (supports OffersV2 and legacy Offers)
     *
     * @param array $item API item
     * @return array Array of listings
     */
    public function get_all_listings(array $item): array {
        if (isset($item['OffersV2']['Listings'])) {
            return $item['OffersV2']['Listings'];
        }
        return $item['Offers']['Listings'] ?? [];
    }

    /**
     * Get price amount (numeric)
     *
     * @param array $item API item
     * @return float|null Price amount or null
     */
    public function get_price_amount(array $item): ?float {
        $listing = $this->get_listing($item);
        if (!$listing) {
            return null;
        }

        // OffersV2 format
        if (isset($listing['Price']['Money']['Amount'])) {
            return (float) $listing['Price']['Money']['Amount'];
        }
        // Legacy Offers format
        if (isset($listing['Price']['Amount'])) {
            return (float) $listing['Price']['Amount'];
        }

        return null;
    }

    /**
     * Get price display string
     *
     * @param array $item API item
     * @return string Price display or empty string
     */
    public function get_price_display(array $item): string {
        $listing = $this->get_listing($item);
        if (!$listing) {
            return '';
        }

        // OffersV2 format
        if (isset($listing['Price']['Money']['DisplayAmount'])) {
            return $listing['Price']['Money']['DisplayAmount'];
        }
        // Legacy Offers format
        return $listing['Price']['DisplayAmount'] ?? '';
    }

    /**
     * Get savings percentage
     *
     * @param array $item API item
     * @return int|null Savings percentage or null
     */
    public function get_savings_percent(array $item): ?int {
        $listing = $this->get_listing($item);
        if (!$listing) {
            return null;
        }

        if (isset($listing['Price']['Savings']['Percentage'])) {
            return (int) $listing['Price']['Savings']['Percentage'];
        }

        return null;
    }

    /**
     * Get savings display amount
     *
     * @param array $item API item
     * @return string Savings display or empty string
     */
    public function get_savings_display(array $item): string {
        $listing = $this->get_listing($item);
        if (!$listing) {
            return '';
        }

        // OffersV2 format
        if (isset($listing['Price']['Savings']['Money']['DisplayAmount'])) {
            return $listing['Price']['Savings']['Money']['DisplayAmount'];
        }
        // Legacy Offers format
        return $listing['Price']['Savings']['DisplayAmount'] ?? '';
    }

    /**
     * Get original price (saving basis) display
     *
     * @param array $item API item
     * @return string Original price display or empty string
     */
    public function get_original_price_display(array $item): string {
        $listing = $this->get_listing($item);
        if (!$listing) {
            return '';
        }

        // OffersV2 format
        if (isset($listing['Price']['SavingBasis']['Money']['DisplayAmount'])) {
            return $listing['Price']['SavingBasis']['Money']['DisplayAmount'];
        }
        // Legacy Offers format
        return $listing['SavingBasis']['DisplayAmount'] ?? '';
    }

    /**
     * Get deal details (OffersV2 only - not available in legacy Offers)
     *
     * @param array $item API item
     * @return array|null Deal details or null
     */
    public function get_deal_details(array $item): ?array {
        // OffersV2 format
        if (isset($item['OffersV2']['Listings'][0]['DealDetails'])) {
            return $item['OffersV2']['Listings'][0]['DealDetails'];
        }
        // Legacy Offers doesn't have DealDetails
        return null;
    }

    /**
     * Check if item is Buy Box winner
     *
     * @param array $item API item
     * @return bool True if Buy Box winner
     */
    public function get_is_buybox_winner(array $item): bool {
        // OffersV2 format
        if (isset($item['OffersV2']['Listings'][0]['IsBuyBoxWinner'])) {
            return !empty($item['OffersV2']['Listings'][0]['IsBuyBoxWinner']);
        }
        // Legacy Offers format
        return !empty($item['Offers']['Listings'][0]['IsBuyBoxWinner']);
    }

    /**
     * Get availability message
     *
     * @param array $item API item
     * @return string Availability message or empty string
     */
    public function get_availability_message(array $item): string {
        $listing = $this->get_listing($item);
        return $listing['Availability']['Message'] ?? '';
    }

    /**
     * Get availability type
     *
     * @param array $item API item
     * @return string Availability type or empty string
     */
    public function get_availability_type(array $item): string {
        $listing = $this->get_listing($item);
        return $listing['Availability']['Type'] ?? '';
    }

    /**
     * Check if stock is scarce
     *
     * @param array $item API item
     * @return bool True if stock is scarce
     */
    public function is_stock_scarce(array $item): bool {
        $type = $this->get_availability_type($item);
        return $type === 'IN_STOCK_SCARCE';
    }

    /**
     * Get condition value
     *
     * @param array $item API item
     * @return string Condition (New, Used, etc.) or empty string
     */
    public function get_condition(array $item): string {
        $listing = $this->get_listing($item);
        return $listing['Condition']['Value'] ?? '';
    }

    /**
     * Get condition sub-condition
     *
     * @param array $item API item
     * @return string Sub-condition (VeryGood, Good, etc.) or empty string
     */
    public function get_sub_condition(array $item): string {
        $listing = $this->get_listing($item);
        return $listing['Condition']['SubCondition'] ?? '';
    }

    /**
     * Get merchant name
     *
     * @param array $item API item
     * @return string Merchant name or empty string
     */
    public function get_merchant_name(array $item): string {
        $listing = $this->get_listing($item);
        return $listing['MerchantInfo']['Name'] ?? '';
    }

    /**
     * Parse price string to float
     *
     * @param string $price_string Price string like "$12.99" or "12,99 €"
     * @return float|null Parsed price or null
     */
    public function parse_price_string(string $price_string): ?float {
        if (empty($price_string)) {
            return null;
        }

        $cleaned = preg_replace('/[^\d.,]/', '', $price_string);

        if (preg_match('/^\d{1,3}(\.\d{3})*(,\d{2})?$/', $cleaned)) {
            $cleaned = str_replace('.', '', $cleaned);
            $cleaned = str_replace(',', '.', $cleaned);
        } else {
            $cleaned = str_replace(',', '', $cleaned);
        }

        $value = (float) $cleaned;
        return $value > 0 ? $value : null;
    }
}
