<?php

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

class AIEO_Wolt_Catalog_Source implements AIEO_Catalog_Source {

    const DEFAULT_BASE  = 'https://pos-integration-service.wolt.com';
    const DEFAULT_TOKEN = 'https://integrations-authentication-service.wolt.com/oauth2/token';
    const MENU_TTL      = 1800; 
    const TOKEN_TTL_FALLBACK = 3600;

    
    private $menu = null;
    private $options_by_id = array();
    private $item_category = array();

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

    public function credential_fields() {
        return array(
            array('name' => 'client_id',     'label' => __('Client ID', 'ai-eshop-optimizer'),     'type' => 'text',     'required' => true),
            array('name' => 'client_secret', 'label' => __('Client Secret', 'ai-eshop-optimizer'), 'type' => 'password', 'required' => true),
            array('name' => 'refresh_token', 'label' => __('OAuth Refresh Token', 'ai-eshop-optimizer'), 'type' => 'password', 'required' => true, 'description' => __('From the Wolt OAuth connect. Single-use — rotates automatically and is kept in sync here.', 'ai-eshop-optimizer')),
            array('name' => 'venue_id',      'label' => __('Venue ID', 'ai-eshop-optimizer'),      'type' => 'text',     'required' => true),
            array('name' => 'base_url',      'label' => __('POS API Base URL', 'ai-eshop-optimizer'), 'type' => 'text', 'required' => false, 'description' => __('Leave blank for the Wolt production endpoint.', 'ai-eshop-optimizer')),
        );
    }

    public function validate_credentials(array $creds) {
        foreach (array('client_id', 'client_secret', 'refresh_token', 'venue_id') as $k) {
            if (empty($creds[$k])) {
                return new WP_Error('wolt_missing_cred', __('Client ID, Client Secret, Refresh Token and Venue ID are all required.', 'ai-eshop-optimizer'));
            }
        }
        return true;
    }

    
    
    

    private function base(array $creds) {
        $b = isset($creds['base_url']) ? trim((string) $creds['base_url']) : '';
        return $b !== '' ? untrailingslashit($b) : self::DEFAULT_BASE;
    }

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

        if (!class_exists('AIEO_MOI_OAuth')) {
            return new WP_Error('wolt_no_oauth_helper', __('The Marketplace Order Importer OAuth helper is unavailable.', 'ai-eshop-optimizer'));
        }
        $resp = AIEO_MOI_OAuth::token_request(
            self::DEFAULT_TOKEN,
            array('grant_type' => 'refresh_token', 'refresh_token' => (string) ($creds['refresh_token'] ?? '')),
            array('user' => (string) ($creds['client_id'] ?? ''), 'pass' => (string) ($creds['client_secret'] ?? ''))
        );
        if (is_wp_error($resp)) { return $resp; }
        $token = (string) ($resp['access_token'] ?? '');
        if ($token === '') {
            return new WP_Error('wolt_no_token', __('Wolt 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_wolt', array());
            if (!is_array($opt)) { $opt = array(); }
            $opt['refresh_token'] = $new_refresh;
            update_option('aieo_catalog_import_wolt', $opt, false);
        }

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

    
    
    

    private function fetch_menu(array $creds) {
        if (is_array($this->menu)) { return $this->menu; }

        $venue = (string) ($creds['venue_id'] ?? '');
        $cache_key = 'aieo_wolt_menu_' . md5($venue . '|' . $this->base($creds));
        $cached = get_transient($cache_key);
        if (is_array($cached)) { return $this->index_menu($cached); }

        $token = $this->token($creds);
        if (is_wp_error($token)) { return $token; }
        $resp = wp_remote_get($this->base($creds) . '/v2/venues/' . rawurlencode($venue) . '/menu', array(
            'timeout' => 45,
            'headers' => array('Authorization' => 'Bearer ' . $token, 'Accept' => 'application/json'),
        ));
        if (is_wp_error($resp)) { return $resp; }
        $code = (int) wp_remote_retrieve_response_code($resp);
        $json = json_decode((string) wp_remote_retrieve_body($resp), true);
        if ($code >= 400) {
            $msg = is_array($json) && !empty($json['message']) ? (string) $json['message'] : ('HTTP ' . $code . ($code === 429 ? ' — Wolt allows one menu read per 15 minutes; try again shortly.' : ''));
            return new WP_Error('wolt_http_' . $code, $msg);
        }
        if (!is_array($json)) { $json = array(); }
        set_transient($cache_key, $json, self::MENU_TTL);
        return $this->index_menu($json);
    }

    
    private function index_menu(array $menu) {
        $this->menu = $menu;
        $this->options_by_id = array();
        foreach ((array) ($menu['options'] ?? array()) as $opt) {
            if (is_array($opt) && !empty($opt['id'])) { $this->options_by_id[(string) $opt['id']] = $opt; }
        }
        
        $this->item_category = array();
        foreach ((array) ($menu['categories'] ?? array()) as $cat) {
            if (!is_array($cat) || empty($cat['id'])) { continue; }
            foreach ((array) ($cat['items'] ?? array()) as $iid) {
                $iid = is_array($iid) ? (string) ($iid['id'] ?? '') : (string) $iid;
                if ($iid !== '') { $this->item_category[$iid] = (string) $cat['id']; }
            }
        }
        return $menu;
    }

    public function fetch_categories(array $creds) {
        $menu = $this->fetch_menu($creds);
        if (is_wp_error($menu)) { return $menu; }
        $map = array();
        foreach ((array) ($menu['categories'] ?? array()) as $cat) {
            if (!is_array($cat) || empty($cat['id'])) { continue; }
            $name = (string) ($cat['name'] ?? '');
            if ($name === '' && !empty($cat['product']['name'])) { $name = (string) $cat['product']['name']; }
            $map[(string) $cat['id']] = array(
                'name'   => $name,
                'parent' => (string) ($cat['parent_id'] ?? ($cat['parent'] ?? '')),
            );
        }
        return $map;
    }

    public function fetch_page(array $creds, $page, $page_size) {
        $menu = $this->fetch_menu($creds);
        if (is_wp_error($menu)) { return $menu; }
        $items = array_values((array) ($menu['items'] ?? array()));
        $size  = max(1, (int) $page_size);
        $total = count($items);
        $offset = max(0, ((int) $page - 1) * $size);
        return array(
            'products'    => array_slice($items, $offset, $size),
            'page'        => (int) $page,
            'total_pages' => max(1, (int) ceil($total / $size)),
            'total'       => $total,
        );
    }

    
    
    

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

        $sku = (string) ($product['sku'] ?? ($product['external_id'] ?? ($product['gtin'] ?? '')));
        if ($sku === '') { $sku = 'wolt-' . $iid; }

        $title   = (string) ($product['name'] ?? '');
        $desc    = (string) ($product['description'] ?? '');
        $img     = (string) ($product['image_url'] ?? '');
        $enabled = !isset($raw['enabled']) || !empty($raw['enabled']);

        
        $cat_terms = array();
        $cid = isset($this->item_category[$iid]) ? $this->item_category[$iid] : (string) ($raw['category_id'] ?? ($raw['category'] ?? ''));
        $cid = (string) $cid;
        $guard = 0;
        while ($cid !== '' && isset($cats[$cid]) && $guard < 16) {
            $node = $cats[$cid];
            if ($node['name'] !== '') {
                $parent_cid = (string) $node['parent'];
                array_unshift($cat_terms, array(
                    'slug'        => sanitize_title($node['name']),
                    'name'        => $node['name'],
                    'parent_slug' => ($parent_cid !== '' && isset($cats[$parent_cid])) ? sanitize_title($cats[$parent_cid]['name']) : '',
                ));
            }
            $cid = (string) $node['parent'];
            $guard++;
        }

        
        $imgs = ($img !== '') ? array(array('src' => $img)) : array();

        $payload = array(
            'type'        => 'simple',
            'title'       => $title,
            'description' => $desc,
            'status'      => (isset($ctx['options']['status']) && $ctx['options']['status'] === 'publish') ? 'publish' : 'draft',
            'match'       => array('sku' => $sku, 'barcode' => (string) ($product['gtin'] ?? '')),
            'regular_price' => isset($raw['price']) ? (string) round(((float) $raw['price']) / 100, 2) : '',
            'stock'       => array('manage' => false, 'status' => $enabled ? 'instock' : 'outofstock'),
            'category_terms' => $cat_terms,
            'images'         => !empty($imgs) ? array($imgs[0]) : array(),
            'gallery'        => array(),
        );

        return array('payload' => $payload, 'option_groups' => $this->map_option_groups($raw));
    }

    
    private function map_option_groups(array $item) {
        $groups = array();
        foreach ((array) ($item['option_bindings'] ?? array()) as $ob) {
            $oid = is_array($ob) ? (string) ($ob['id'] ?? ($ob['option_id'] ?? '')) : (string) $ob;
            if ($oid === '' || empty($this->options_by_id[$oid])) { continue; }
            $opt  = $this->options_by_id[$oid];
            $type = (string) ($opt['type'] ?? '');
            $mc   = isset($opt['multi_choice_config']) && is_array($opt['multi_choice_config']) ? $opt['multi_choice_config'] : array();

            $values = array();
            foreach ((array) ($opt['values'] ?? array()) as $v) {
                if (!is_array($v)) { continue; }
                $vp    = isset($v['product']) && is_array($v['product']) ? $v['product'] : array();
                $label = (string) ($vp['name'] ?? ($v['name'] ?? ''));
                if ($label === '') { continue; }
                $values[] = array(
                    'slug'        => 'wolt-' . (string) ($v['id'] ?? sanitize_title($label)),
                    'label'       => $label,
                    'price_delta' => isset($v['price']) ? round(((float) $v['price']) / 100, 4) : 0,
                );
            }
            if (empty($values)) { continue; }

            $groups[] = array(
                'slug'        => 'wolt-' . $oid,
                'name'        => (string) ($opt['name'] ?? ''),
                'select_type' => (stripos($type, 'multi') !== false) ? 'checkbox' : 'radio',
                'min_select'  => isset($mc['min']) ? (int) $mc['min'] : (isset($mc['min_selection']) ? (int) $mc['min_selection'] : 0),
                'max_select'  => isset($mc['max']) ? (int) $mc['max'] : (isset($mc['max_selection']) ? (int) $mc['max_selection'] : 0),
                'options'     => $values,
            );
        }
        return $groups;
    }
}
