<?php

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

class AIEO_Etsy_Catalog_Source implements AIEO_Catalog_Source {

    const API_BASE  = 'https://openapi.etsy.com/v3/application';
    const TOKEN_URL = 'https://api.etsy.com/v3/public/oauth/token';
    const TOKEN_TTL_FALLBACK = 3600;

    public function slug()  { return 'etsy'; }
    public function label() { return __('Etsy', 'ai-eshop-optimizer'); }

    public function credential_fields() {
        return array(
            array('name' => 'keystring',     'label' => __('API Key (keystring)', 'ai-eshop-optimizer'),  'type' => 'text',     'required' => true,  'description' => __('Your Etsy app keystring — also sent as the x-api-key + OAuth client id.', 'ai-eshop-optimizer')),
            array('name' => 'refresh_token', 'label' => __('OAuth Refresh Token', 'ai-eshop-optimizer'),  'type' => 'password', 'required' => true,  'description' => __('From the Etsy OAuth connect (listings_r scope). Rotates automatically — kept in sync here.', 'ai-eshop-optimizer')),
            array('name' => 'shop_id',       'label' => __('Shop ID', 'ai-eshop-optimizer'),              'type' => 'text',     'required' => true),
        );
    }

    public function validate_credentials(array $creds) {
        foreach (array('keystring', 'refresh_token', 'shop_id') as $k) {
            if (empty($creds[$k])) {
                return new WP_Error('etsy_missing_cred', __('API Key, OAuth Refresh Token and Shop ID are all required.', 'ai-eshop-optimizer'));
            }
        }
        return true;
    }

    
    
    

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

        if (!class_exists('AIEO_MOI_OAuth')) {
            return new WP_Error('etsy_no_oauth_helper', __('The Marketplace Order Importer OAuth helper is unavailable.', 'ai-eshop-optimizer'));
        }
        $resp = AIEO_MOI_OAuth::token_request(self::TOKEN_URL, array(
            'grant_type'    => 'refresh_token',
            'client_id'     => (string) ($creds['keystring'] ?? ''),
            'refresh_token' => (string) ($creds['refresh_token'] ?? ''),
        ));
        if (is_wp_error($resp)) { return $resp; }
        $token = (string) ($resp['access_token'] ?? '');
        if ($token === '') {
            return new WP_Error('etsy_no_token', __('Etsy did not return an access token — re-run the OAuth connect.', 'ai-eshop-optimizer'));
        }

        
        $new_refresh = (string) ($resp['refresh_token'] ?? '');
        if ($new_refresh !== '' && $new_refresh !== (string) ($creds['refresh_token'] ?? '')) {
            $opt = get_option('aieo_catalog_import_etsy', array());
            if (!is_array($opt)) { $opt = array(); }
            $opt['refresh_token'] = $new_refresh;
            update_option('aieo_catalog_import_etsy', $opt, false);
        }

        $ttl = (int) ($resp['expires_in'] ?? self::TOKEN_TTL_FALLBACK);
        set_transient($cache_key, $token, max(60, $ttl - 120));
        return $token;
    }

    private function api_get(array $creds, $path, array $query = array()) {
        $token = $this->token($creds);
        if (is_wp_error($token)) { return $token; }
        $url = self::API_BASE . $path;
        if (!empty($query)) { $url = add_query_arg($query, $url); }
        $resp = wp_remote_get($url, array(
            'timeout' => 30,
            'headers' => array(
                'x-api-key'     => (string) ($creds['keystring'] ?? ''),
                'Authorization' => 'Bearer ' . $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 = is_array($json) && !empty($json['error']) ? (string) $json['error'] : ('HTTP ' . $code);
            return new WP_Error('etsy_http_' . $code, $msg);
        }
        return is_array($json) ? $json : array();
    }

    
    
    

    public function fetch_categories(array $creds) {
        
        $res = $this->api_get($creds, '/shops/' . rawurlencode((string) $creds['shop_id']) . '/sections');
        if (is_wp_error($res)) { return $res; }
        $map = array();
        foreach ((array) ($res['results'] ?? array()) as $s) {
            if (!is_array($s) || empty($s['shop_section_id'])) { continue; }
            $map[(string) $s['shop_section_id']] = array(
                'name'   => (string) ($s['title'] ?? ''),
                'parent' => '',
            );
        }
        return $map;
    }

    public function fetch_page(array $creds, $page, $page_size) {
        $limit  = max(1, min(100, (int) $page_size));
        $offset = max(0, ((int) $page - 1) * $limit);
        $res = $this->api_get($creds, '/shops/' . rawurlencode((string) $creds['shop_id']) . '/listings', array(
            'state'    => 'active',
            'limit'    => $limit,
            'offset'   => $offset,
            'includes' => 'Images,Inventory',
        ));
        if (is_wp_error($res)) { return $res; }
        $count = (int) ($res['count'] ?? 0);
        return array(
            'products'    => (array) ($res['results'] ?? array()),
            'page'        => (int) $page,
            'total_pages' => max(1, (int) ceil($count / $limit)),
            'total'       => $count,
        );
    }

    
    
    

    public function map_product(array $raw, array $ctx) {
        $cats = isset($ctx['categories']) && is_array($ctx['categories']) ? $ctx['categories'] : array();
        $lid  = (string) ($raw['listing_id'] ?? '');

        
        $sku = '';
        if (!empty($raw['skus']) && is_array($raw['skus'])) { $sku = (string) reset($raw['skus']); }
        if ($sku === '' && !empty($raw['inventory']['products'][0]['sku'])) { $sku = (string) $raw['inventory']['products'][0]['sku']; }
        if ($sku === '') { $sku = 'etsy-' . $lid; }

        
        $price = $this->money($raw['price'] ?? null);
        if ($price === '' && !empty($raw['inventory']['products'][0]['offerings'][0]['price'])) {
            $price = $this->money($raw['inventory']['products'][0]['offerings'][0]['price']);
        }

        
        $qty = null;
        if (isset($raw['quantity'])) { $qty = (int) $raw['quantity']; }
        elseif (isset($raw['inventory']['products'][0]['offerings'][0]['quantity'])) { $qty = (int) $raw['inventory']['products'][0]['offerings'][0]['quantity']; }

        
        $cat_terms = array();
        $sid = (string) ($raw['shop_section_id'] ?? '');
        if ($sid !== '' && isset($cats[$sid]) && $cats[$sid]['name'] !== '') {
            $cat_terms[] = array('slug' => sanitize_title($cats[$sid]['name']), 'name' => $cats[$sid]['name'], 'parent_slug' => '');
        }

        
        $imgs = array();
        foreach ((array) ($raw['images'] ?? array()) as $im) {
            if (!is_array($im)) { continue; }
            $u = (string) ($im['url_fullxfull'] ?? ($im['url_570xN'] ?? ($im['url'] ?? '')));
            if ($u !== '') { $imgs[] = array('src' => $u); }
        }

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

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

    
    private function money($m) {
        if (is_array($m) && isset($m['amount'], $m['divisor']) && (int) $m['divisor'] > 0) {
            return (string) round((float) $m['amount'] / (float) $m['divisor'], 2);
        }
        return '';
    }
}
