<?php

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

class AIEO_MOI_Provider_Efood implements AIEO_MOI_Provider {

    const DEFAULT_BASE = 'https://efood.partner.deliveryhero.io';

    public function slug()  { return 'efood'; }
    public function label() { return 'eFood'; }

    
    public function is_polling() { return false; }

    public function info_text() {
        return '<strong>' . esc_html__('eFood / DeliveryHero Partner API', 'ai-eshop-optimizer') . '</strong><br>'
             . esc_html__('Delivery: Webhook (push). Paste the webhook URL below into the eFood vendor portal, and set the same secret token here + there (verified on every inbound call).', 'ai-eshop-optimizer') . '<br>'
             . esc_html__('Outbound status updates use OAuth2 client-credentials. Set the chain id + vendor id eFood assigned you.', 'ai-eshop-optimizer');
    }

    public function credential_fields() {
        return array(
            array('name' => 'webhook_secret', 'label' => __('Webhook auth token', 'ai-eshop-optimizer'), 'type' => 'password', 'required' => true,  'description' => __('The static token eFood sends in the Authorization header. Must match the value configured in the eFood vendor portal.', 'ai-eshop-optimizer')),
            array('name' => 'client_id',      'label' => __('OAuth client id', 'ai-eshop-optimizer'),     'type' => 'text',     'required' => false, 'description' => __('For outbound status updates (client-credentials).', 'ai-eshop-optimizer')),
            array('name' => 'client_secret',  'label' => __('OAuth client secret', 'ai-eshop-optimizer'), 'type' => 'password', 'required' => false, 'description' => __('OAuth client secret.', 'ai-eshop-optimizer')),
            array('name' => 'chain_id',       'label' => __('Chain id', 'ai-eshop-optimizer'),            'type' => 'text',     'required' => false, 'description' => __('eFood chain id (status-update paths are chain-scoped).', 'ai-eshop-optimizer')),
            array('name' => 'vendor_id',      'label' => __('Vendor id', 'ai-eshop-optimizer'),           'type' => 'text',     'required' => false, 'description' => __('eFood vendor/outlet id.', 'ai-eshop-optimizer')),
            array('name' => 'base_url',       'label' => __('API base URL', 'ai-eshop-optimizer'),        'type' => 'text',     'required' => false, 'description' => __('Defaults to the production Partner API; override for a sandbox base supplied by eFood.', 'ai-eshop-optimizer')),
        );
    }

    public function validate_credentials(array $credentials) {
        return !empty($credentials['webhook_secret']);
    }

    public function verify_webhook($request, array $vendor) {
        $expected = (string) ($vendor['credentials']['webhook_secret'] ?? '');
        if ($expected === '') {
            return new WP_Error('efood_no_secret', __('eFood webhook secret is not configured.', 'ai-eshop-optimizer'));
        }
        $got = (string) $request->get_header('authorization');
        $got = trim(preg_replace('/^Bearer\s+/i', '', $got));
        if ($got === '' || !hash_equals($expected, $got)) {
            return new WP_Error('efood_bad_auth', __('eFood webhook Authorization token mismatch.', 'ai-eshop-optimizer'));
        }
        return true;
    }

    public function parse_webhook_payload(array $body) {
        if (empty($body['order_id'])) { return array(); }

        $cust = isset($body['customer']) && is_array($body['customer']) ? $body['customer'] : array();
        $addr = isset($cust['delivery_address']) && is_array($cust['delivery_address']) ? $cust['delivery_address'] : array();
        $address = array(
            'first_name' => (string) ($cust['first_name'] ?? ''),
            'last_name'  => (string) ($cust['last_name'] ?? ''),
            'company'    => '',
            'address_1'  => trim((string) ($addr['street'] ?? '') . ' ' . (string) ($addr['number'] ?? '')),
            'address_2'  => trim((string) ($addr['building'] ?? '') . ' ' . (string) ($addr['floor'] ?? '') . ' ' . (string) ($addr['apartment'] ?? '')),
            'city'       => (string) ($addr['city'] ?? ''),
            'state'      => '',
            'postcode'   => (string) ($addr['zipcode'] ?? ''),
            'country'    => (string) ($addr['country'] ?? ''),
            'email'      => (string) ($cust['email'] ?? ''),
            'phone'      => (string) ($cust['phone_number'] ?? ''),
        );

        $line_items = array();
        foreach ((array) ($body['items'] ?? array()) as $it) {
            if (!is_array($it)) { continue; }
            $op  = isset($it['original_pricing']) && is_array($it['original_pricing']) ? $it['original_pricing'] : array();
            $bc  = isset($it['barcode']) && is_array($it['barcode']) ? ($it['barcode'][0] ?? '') : ($it['barcode'] ?? '');
            $line_items[] = array(
                'remote_id'  => (string) ($it['sku'] ?? $bc),
                'qty'        => (int) ($op['quantity'] ?? ($it['quantity'] ?? 1)),
                'unit_price' => $this->num($op['unit_price'] ?? ($it['unit_price'] ?? 0)),
                'tax'        => 0.0,
                'title'      => (string) ($it['name'] ?? ''),
            );
        }

        $pay    = isset($body['payment']) && is_array($body['payment']) ? $body['payment'] : array();
        $status = (string) ($body['status'] ?? '');
        $event_type = ('CANCELLED' === $status) ? 'order_cancelled' : ('RECEIVED' === $status ? 'new_order' : 'order_updated');

        return array(
            'event_type'      => $event_type,
            'remote_order_id' => (string) $body['order_id'],
            'remote_code'     => (string) ($body['order_code'] ?? ($body['external_order_id'] ?? '')),
            'state'           => $status !== '' ? $status : 'unknown',
            'billing'         => $address,
            'shipping'        => $address,
            'line_items'      => $line_items,
            'totals'          => array(
                'shipping' => $this->num($pay['delivery_fee'] ?? 0),
                'tax'      => $this->num($pay['total_taxes'] ?? 0),
                'fees'     => $this->num($pay['service_fee'] ?? 0),
                'total'    => $this->num($pay['order_total'] ?? 0),
            ),
            'courier'         => (string) ($body['transport_type'] ?? ''),
            'voucher_url'     => '',
            'tracking_codes'  => array(),
            'invoice'         => null,
            'gift_wrap'       => false,
            'raw'             => $body,
            'created_at'      => !empty($body['accepted_for']) ? (int) strtotime((string) $body['accepted_for']) : 0,
        );
    }

    public function accept_order(array $vendor, $remote_order_id, array $opts = array()) {
        $order = $this->get_order($vendor, $remote_order_id);
        if (is_wp_error($order)) { return array('ok' => false, 'message' => $order->get_error_message()); }
        $status = ('VENDOR_DELIVERY' === (string) ($order['transport_type'] ?? '')) ? 'DISPATCHED' : 'READY_FOR_PICKUP';
        $res = $this->put_status($vendor, $remote_order_id, $order, $status, null);
        if (is_wp_error($res)) { return array('ok' => false, 'message' => $res->get_error_message()); }
        
        return array('ok' => true, 'message' => sprintf(__('eFood order moved to %s.', 'ai-eshop-optimizer'), $status));
    }

    public function reject_order(array $vendor, $remote_order_id, $reason = '') {
        $order = $this->get_order($vendor, $remote_order_id);
        if (is_wp_error($order)) { return array('ok' => false, 'message' => $order->get_error_message()); }
        $efood_reason = $this->map_cancel_reason((string) $reason);
        $res = $this->put_status($vendor, $remote_order_id, $order, 'CANCELLED', $efood_reason);
        if (is_wp_error($res)) { return array('ok' => false, 'message' => $res->get_error_message()); }
        return array('ok' => true, 'message' => __('eFood order cancelled.', 'ai-eshop-optimizer'));
    }

    public function fetch_voucher(array $vendor, $remote_order_id) {
        return ''; 
    }

    public function poll_orders(array $vendor, $since_ts) { return array(); }
    public function backfill_orders(array $vendor, $since_ts, $until_ts) { return array(); }

    

    
    private function num($v) {
        if (is_array($v)) {
            if (isset($v['Value']))  { return (float) $v['Value']; }
            if (isset($v['value']))  { return (float) $v['value']; }
            if (isset($v['amount'])) { return (float) $v['amount']; }
            return 0.0;
        }
        return (float) $v;
    }

    private function map_cancel_reason($reason) {
        $r = strtolower((string) $reason);
        if (strpos($r, 'stock') !== false || strpos($r, 'unavail') !== false) { return 'ITEM_UNAVAILABLE'; }
        if (strpos($r, 'busy') !== false || strpos($r, 'time') !== false)     { return 'TOO_BUSY'; }
        return 'CLOSED';
    }

    private function base(array $vendor) {
        $b = (string) ($vendor['credentials']['base_url'] ?? '');
        return rtrim($b !== '' ? $b : self::DEFAULT_BASE, '/');
    }

    private function chain_path(array $vendor, $order_id) {
        $chain = rawurlencode((string) ($vendor['credentials']['chain_id'] ?? ''));
        return '/v2/chains/' . $chain . '/orders/' . rawurlencode((string) $order_id);
    }

    
    private function token(array $vendor) {
        return AIEO_MOI_OAuth::access_token($vendor, function ($oauth_state, $creds) use ($vendor) {
            if (empty($creds['client_id']) || empty($creds['client_secret'])) {
                return new WP_Error('efood_no_oauth', __('eFood OAuth client id/secret are required for status updates.', 'ai-eshop-optimizer'));
            }
            return AIEO_MOI_OAuth::token_request($this->base($vendor) . '/v2/oauth/token', array(
                'grant_type'    => 'client_credentials',
                'client_id'     => (string) $creds['client_id'],
                'client_secret' => (string) $creds['client_secret'],
            ));
        });
    }

    private function get_order(array $vendor, $order_id) {
        $token = $this->token($vendor);
        if (is_wp_error($token)) { return $token; }
        $resp = wp_remote_get($this->base($vendor) . $this->chain_path($vendor, $order_id), array(
            'timeout' => 25,
            'headers' => array('Authorization' => 'Bearer ' . $token, 'Accept' => 'application/json'),
        ));
        return $this->decode($resp);
    }

    private function put_status(array $vendor, $order_id, array $order, $status, $cancel_reason) {
        $token = $this->token($vendor);
        if (is_wp_error($token)) { return $token; }

        
        
        $items = array();
        foreach ((array) ($order['items'] ?? array()) as $it) {
            if (!is_array($it)) { continue; }
            $items[] = array(
                'sku'    => (string) ($it['sku'] ?? ''),
                'status' => ('CANCELLED' === $status) ? 'NOT_FOUND' : 'IN_CART',
            );
        }
        $payload = array('order_id' => (string) $order_id, 'items' => $items, 'status' => $status);
        if ('CANCELLED' === $status && $cancel_reason) {
            $payload['cancellation'] = array('reason' => $cancel_reason);
        }

        $resp = wp_remote_request($this->base($vendor) . $this->chain_path($vendor, $order_id), array(
            'method'  => 'PUT',
            'timeout' => 25,
            'headers' => array('Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json', 'Accept' => 'application/json'),
            'body'    => wp_json_encode($payload),
        ));
        return $this->decode($resp);
    }

    private function decode($resp) {
        if (is_wp_error($resp)) { return $resp; }
        $code = (int) wp_remote_retrieve_response_code($resp);
        $raw  = (string) wp_remote_retrieve_body($resp);
        $json = json_decode($raw, true);
        if ($code >= 400) {
            $msg = is_array($json) && !empty($json['Errors'][0]['Message']) ? (string) $json['Errors'][0]['Message']
                
                : sprintf(__('eFood API HTTP %d', 'ai-eshop-optimizer'), $code);
            return new WP_Error('efood_api_error', $msg, array('status' => $code, 'body' => $raw));
        }
        return is_array($json) ? $json : array();
    }
}

AIEO_MOI_Provider_Registry::register(new AIEO_MOI_Provider_Efood());
