<?php

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

class AIEO_Amazon_Catalog_Source implements AIEO_Catalog_Source {

    const LWA_TOKEN_URL    = 'https://api.amazon.com/auth/o2/token';
    const TOKEN_TTL_FALLBACK = 3600;
    const PAGE_SIZE_MAX    = 20; 

    private static $hosts = array(
        'na' => 'https://sellingpartnerapi-na.amazon.com',
        'eu' => 'https://sellingpartnerapi-eu.amazon.com',
        'fe' => 'https://sellingpartnerapi-fe.amazon.com',
    );

    public function slug()  { return 'amazon'; }
    public function label() { return __('Amazon (SP-API)', 'ai-eshop-optimizer'); }

    public function credential_fields() {
        return array(
            array('name' => 'lwa_client_id',     'label' => __('LWA client id', 'ai-eshop-optimizer'),       'type' => 'text',     'required' => true,  'description' => __('From your SP-API app (Login with Amazon).', 'ai-eshop-optimizer')),
            array('name' => 'lwa_client_secret', 'label' => __('LWA client secret', 'ai-eshop-optimizer'),   'type' => 'password', 'required' => true),
            array('name' => 'refresh_token',     'label' => __('Seller refresh token', 'ai-eshop-optimizer'),'type' => 'password', 'required' => true,  'description' => __('Long-lived refresh token from the seller’s app authorisation (roles: Product Listing).', 'ai-eshop-optimizer')),
            array('name' => 'region',            'label' => __('Region (na / eu / fe)', 'ai-eshop-optimizer'),'type' => 'text',    'required' => true,  'description' => __('na = North America, eu = Europe, fe = Far East. Picks the SP-API host.', 'ai-eshop-optimizer')),
            array('name' => 'seller_id',         'label' => __('Seller ID (merchant token)', 'ai-eshop-optimizer'),'type' => 'text','required' => true,  'description' => __('Your selling-partner / merchant id (Seller Central → Account Info).', 'ai-eshop-optimizer')),
            array('name' => 'marketplace_id',    'label' => __('Marketplace ID', 'ai-eshop-optimizer'),      'type' => 'text',     'required' => true,  'description' => __('e.g. A1PA6795UKMFR9 (DE), ATVPDKIKX0DER (US), A21TJRUUN4KGV (IN).', 'ai-eshop-optimizer')),
        );
    }

    public function validate_credentials(array $creds) {
        foreach (array('lwa_client_id', 'lwa_client_secret', 'refresh_token', 'region', 'seller_id', 'marketplace_id') as $k) {
            if (empty($creds[$k])) {
                return new WP_Error('amazon_missing_cred', __('LWA client id/secret, seller refresh token, region, Seller ID and Marketplace ID are all required.', 'ai-eshop-optimizer'));
            }
        }
        $r = strtolower((string) $creds['region']);
        if (!isset(self::$hosts[$r])) {
            return new WP_Error('amazon_bad_region', __('Region must be one of na, eu or fe.', 'ai-eshop-optimizer'));
        }
        return true;
    }

    
    
    

    private function token(array $creds) {
        $cache_key = 'aieo_amzn_cat_tok_' . md5((string) ($creds['lwa_client_id'] ?? '') . '|' . (string) ($creds['region'] ?? ''));
        $cached = get_transient($cache_key);
        if (is_string($cached) && $cached !== '') { return $cached; }

        if (!class_exists('AIEO_MOI_OAuth')) {
            return new WP_Error('amazon_no_oauth_helper', __('The Marketplace Order Importer OAuth helper is unavailable.', 'ai-eshop-optimizer'));
        }
        $resp = AIEO_MOI_OAuth::token_request(self::LWA_TOKEN_URL, array(
            'grant_type'    => 'refresh_token',
            'refresh_token' => (string) ($creds['refresh_token'] ?? ''),
            'client_id'     => (string) ($creds['lwa_client_id'] ?? ''),
            'client_secret' => (string) ($creds['lwa_client_secret'] ?? ''),
        ));
        if (is_wp_error($resp)) { return $resp; }
        $token = (string) ($resp['access_token'] ?? '');
        if ($token === '') {
            return new WP_Error('amazon_no_token', __('Amazon did not return an access token — re-check the LWA credentials / refresh token.', 'ai-eshop-optimizer'));
        }
        $ttl = (int) ($resp['expires_in'] ?? self::TOKEN_TTL_FALLBACK);
        set_transient($cache_key, $token, max(60, $ttl - 120));
        return $token;
    }

    private function host(array $creds) {
        $r = strtolower((string) ($creds['region'] ?? 'eu'));
        return isset(self::$hosts[$r]) ? self::$hosts[$r] : self::$hosts['eu'];
    }

    private function api_get(array $creds, $path, array $query = array()) {
        $token = $this->token($creds);
        if (is_wp_error($token)) { return $token; }
        $url = $this->host($creds) . $path;
        if (!empty($query)) { $url = add_query_arg($query, $url); }
        $resp = wp_remote_get($url, array(
            'timeout' => 30,
            'headers' => array(
                'x-amz-access-token' => $token,
                'Accept'             => 'application/json',
            ),
        ));
        if (is_wp_error($resp)) { return $resp; }
        $code = (int) wp_remote_retrieve_response_code($resp);
        $body = (string) wp_remote_retrieve_body($resp);
        $json = json_decode($body, true);
        if ($code >= 400) {
            $msg = '';
            if (is_array($json) && !empty($json['errors'][0]['message'])) { $msg = (string) $json['errors'][0]['message']; }
            return new WP_Error('amazon_http_' . $code, $msg !== '' ? $msg : ('HTTP ' . $code));
        }
        return is_array($json) ? $json : array();
    }

    
    
    

    
    public function fetch_categories(array $creds) {
        return array();
    }

    public function fetch_page(array $creds, $page, $page_size) {
        $size = max(1, min(self::PAGE_SIZE_MAX, (int) $page_size));
        $seller = (string) ($creds['seller_id'] ?? '');
        $cur_key = 'aieo_amzn_listcur_' . md5($seller . '|' . (string) ($creds['marketplace_id'] ?? ''));

        $query = array(
            'marketplaceIds' => (string) ($creds['marketplace_id'] ?? ''),
            'pageSize'       => $size,
            'includedData'   => 'summaries,offers,fulfillmentAvailability,attributes',
        );
        if ((int) $page <= 1) {
            
            delete_transient($cur_key);
        } else {
            $tok = get_transient($cur_key);
            if (is_string($tok) && $tok !== '') { $query['pageToken'] = $tok; }
        }

        $res = $this->api_get($creds, '/listings/2021-08-01/items/' . rawurlencode($seller), $query);
        if (is_wp_error($res)) { return $res; }

        $items = (array) ($res['items'] ?? array());
        $next  = (string) ($res['pagination']['nextToken'] ?? '');
        if ($next !== '') {
            set_transient($cur_key, $next, 30 * MINUTE_IN_SECONDS);
        } else {
            delete_transient($cur_key);
        }

        return array(
            'products'    => $items,
            'page'        => (int) $page,
            
            
            'total_pages' => $next !== '' ? ((int) $page + 1) : max(1, (int) $page),
            'total'       => (int) ($res['numberOfResults'] ?? 0),
        );
    }

    
    
    

    public function map_product(array $raw, array $ctx) {
        $sku = (string) ($raw['sku'] ?? '');

        $sum = (isset($raw['summaries'][0]) && is_array($raw['summaries'][0])) ? $raw['summaries'][0] : array();
        $title = (string) ($sum['itemName'] ?? '');
        $asin  = (string) ($sum['asin'] ?? '');
        if ($sku === '') { $sku = $asin !== '' ? ('amzn-' . $asin) : ''; }

        
        $price = '';
        $offer = (isset($raw['offers'][0]) && is_array($raw['offers'][0])) ? $raw['offers'][0] : array();
        if (isset($offer['price']['amount'])) {
            $price = (string) $offer['price']['amount'];
        } elseif (isset($offer['price']['Amount'])) {
            $price = (string) $offer['price']['Amount'];
        }

        
        $qty = null;
        if (isset($raw['fulfillmentAvailability'][0]['quantity'])) {
            $qty = (int) $raw['fulfillmentAvailability'][0]['quantity'];
        }

        
        $statuses = array_map('strval', (array) ($sum['status'] ?? array()));
        $instock  = in_array('BUYABLE', $statuses, true) || ($qty === null) || ($qty > 0);

        
        $imgs = array();
        $main = (string) ($sum['mainImage']['link'] ?? '');
        if ($main !== '') { $imgs[] = array('src' => $main); }

        $payload = array(
            'type'        => 'simple',
            'title'       => $title,
            'description' => '',
            'status'      => (isset($ctx['options']['status']) && $ctx['options']['status'] === 'publish') ? 'publish' : 'draft',
            'match'       => array('sku' => $sku, 'barcode' => $this->extract_barcode($raw['attributes'] ?? array())),
            'regular_price' => $price,
            'stock'       => array(
                'manage'   => $qty !== null,
                'quantity' => $qty,
                'status'   => $instock ? 'instock' : 'outofstock',
            ),
            'category_terms' => array(),
            'images'         => !empty($imgs) ? array($imgs[0]) : array(),
            'gallery'        => array(),
        );

        return array('payload' => $payload, 'option_groups' => array());
    }

    
    private function extract_barcode($attributes) {
        if (!is_array($attributes)) { return ''; }
        $eapi = $attributes['externally_assigned_product_identifier'] ?? null;
        if (is_array($eapi)) {
            foreach ($eapi as $entry) {
                if (is_array($entry) && !empty($entry['value'])) { return (string) $entry['value']; }
            }
        }
        foreach (array('ean', 'upc', 'gtin') as $k) {
            if (isset($attributes[$k][0]['value']) && $attributes[$k][0]['value'] !== '') {
                return (string) $attributes[$k][0]['value'];
            }
        }
        return '';
    }
}
