<?php

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

class AIEO_MOI_Provider_Shopflix implements AIEO_MOI_Provider {

    
    
    
    
    
    
    
    
    
    
    const API_BASE = 'https://merchant.api.shopflix.gr/v2';

    public function slug()  { return 'shopflix'; }
    public function label() { return 'Shopflix'; }

    
    public function info_text() {
        return '<strong>' . esc_html__('Shopflix Merchant API (v2)', 'ai-eshop-optimizer') . '</strong><br>'
             
             . sprintf(__('Endpoint: %s', 'ai-eshop-optimizer'), '<code>' . esc_html(self::API_BASE) . '</code>') . '<br>'
             . sprintf(
                 
                 __('Auth: HTTP Basic — username + API key from %s → API credentials', 'ai-eshop-optimizer'),
                 '<a href="https://merchant.shopflix.gr/" target="_blank" rel="noopener noreferrer">merchant.shopflix.gr</a>'
             ) . '<br>'
             . sprintf(
                 
                 __('Docs: %s', 'ai-eshop-optimizer'),
                 '<a href="https://developer.shopflix.gr/" target="_blank" rel="noopener noreferrer">developer.shopflix.gr</a>'
             );
    }

    public function credential_fields() {
        return array(
            array(
                'name'        => 'username',
                'label'       => __('Merchant API Username', 'ai-eshop-optimizer'),
                'type'        => 'text',
                'required'    => true,
                'description' => __('From Shopflix merchant dashboard → API credentials.', 'ai-eshop-optimizer'),
            ),
            array(
                'name'        => 'password',
                'label'       => __('Merchant API Password', 'ai-eshop-optimizer'),
                'type'        => 'password',
                'required'    => true,
                'description' => __('Stored in DB; used as HTTP Basic auth on every request.', 'ai-eshop-optimizer'),
            ),
        );
    }

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

    
    public function verify_webhook($request, array $vendor) {
        return new WP_Error('no_webhooks', __('Shopflix is poll-only — no webhook delivery.', 'ai-eshop-optimizer'));
    }

    public function parse_webhook_payload(array $body) {
        
        
        return array();
    }

    public function accept_order(array $vendor, $remote_order_id, array $opts = array()) {
        
        $resp = $this->api_request($vendor, 'PATCH', '/orders/' . rawurlencode((string) $remote_order_id) . '/accept', null);
        if (is_wp_error($resp)) {
            return array('ok' => false, 'message' => $resp->get_error_message());
        }
        
        
        $voucher_url = $this->create_and_store_voucher($vendor, (string) $remote_order_id);
        return array(
            'ok'          => true,
            'message'     => __('Order accepted on Shopflix.', 'ai-eshop-optimizer'),
            'voucher_url' => $voucher_url,
        );
    }

    public function reject_order(array $vendor, $remote_order_id, $reason = '') {
        
        
        $valid = array('damaged', 'out-of-stock', 'wrong-price', 'disabled-product', 'wrong-product');
        $reason_clean = strtolower(trim((string) $reason));
        $reason_clean = str_replace(' ', '-', $reason_clean);
        if (!in_array($reason_clean, $valid, true)) {
            $reason_clean = 'out-of-stock';
        }
        $resp = $this->api_request($vendor, 'PATCH', '/orders/' . rawurlencode((string) $remote_order_id) . '/reject', array(
            'status' => 'D',
            'reason' => $reason_clean,
        ));
        if (is_wp_error($resp)) {
            return array('ok' => false, 'message' => $resp->get_error_message());
        }
        return array('ok' => true, 'message' => __('Order rejected on Shopflix.', 'ai-eshop-optimizer'));
    }

    public function fetch_voucher(array $vendor, $remote_order_id) {
        return (string) $this->create_and_store_voucher($vendor, (string) $remote_order_id);
    }

    
    public function poll_orders(array $vendor, $since_ts) {
        return $this->fetch_window($vendor, (int) $since_ts, 0);
    }

    
    public function backfill_orders(array $vendor, $since_ts, $until_ts) {
        return $this->fetch_window($vendor, (int) $since_ts, (int) $until_ts);
    }

    
    
    public function list_window_page(array $vendor, $since_ts, $until_ts, $page = 1, $per_page = 50) {
        $since_iso = gmdate('c', max(0, (int) $since_ts));
        $until     = (int) $until_ts > 0 ? (int) $until_ts : 0;
        $page      = max(1, (int) $page);
        $per_page  = max(1, min(50, (int) $per_page));

        $resp = $this->api_request($vendor, 'GET', '/orders?' . http_build_query(array(
            'page'         => $page,
            'itemsPerPage' => $per_page,
            'dateFrom'     => $since_iso,
        )), null);

        if (is_wp_error($resp)) {
            return new WP_Error('shopflix_list_failed', $resp->get_error_message());
        }
        if (!is_array($resp)) {
            return new WP_Error('shopflix_list_failed', __('Empty response.', 'ai-eshop-optimizer'));
        }

        $list   = isset($resp['orders']) && is_array($resp['orders']) ? $resp['orders'] : array();
        $params = isset($resp['params']) && is_array($resp['params']) ? $resp['params'] : array();
        $total  = (int) ($params['totalItems']   ?? 0);
        $per    = (int) ($params['itemsPerPage'] ?? $per_page);

        $ids = array();
        foreach ($list as $summary) {
            $oid = (string) ($summary['id'] ?? '');
            if ($oid === '') { continue; }
            if ($until > 0) {
                $created_iso = (string) ($summary['createdAt'] ?? $summary['createdDate'] ?? '');
                $ts          = $created_iso !== '' ? (int) strtotime($created_iso . ' UTC') : 0;
                if ($ts > 0 && $ts > $until) { continue; }
            }
            $ids[] = $oid;
        }

        $has_more = $per > 0 && ($page * $per) < $total;

        return array(
            'ids'      => $ids,
            'has_more' => $has_more,
            'total'    => $total,
            'page'     => $page,
            'per_page' => $per,
        );
    }

    public function list_window_summaries(array $vendor, $since_ts, $until_ts) {
        $since_iso = gmdate('c', max(0, (int) $since_ts));
        $until     = (int) $until_ts > 0 ? (int) $until_ts : 0;
        $page      = 1;
        $out       = array();
        $loop_guard = 0;

        
        
        
        
        while ($loop_guard++ < 200) {
            $resp = $this->api_request($vendor, 'GET', '/orders?' . http_build_query(array(
                'page'         => $page,
                'itemsPerPage' => 50,
                'dateFrom'     => $since_iso,
            )), null);
            if (is_wp_error($resp) || !is_array($resp)) { break; }
            $list = isset($resp['orders']) && is_array($resp['orders']) ? $resp['orders'] : array();
            if (empty($list)) { break; }

            foreach ($list as $summary) {
                $oid = (string) ($summary['id'] ?? '');
                if ($oid === '') { continue; }
                $created_iso = (string) ($summary['createdAt'] ?? $summary['createdDate'] ?? '');
                if ($until > 0) {
                    $ts = $created_iso !== '' ? (int) strtotime($created_iso . ' UTC') : 0;
                    if ($ts > 0 && $ts > $until) { continue; }
                }
                $out[] = array(
                    'id'        => $oid,
                    'createdAt' => $created_iso,
                    'state'     => (string) ($summary['state'] ?? ''),
                );
            }

            $params = isset($resp['params']) && is_array($resp['params']) ? $resp['params'] : array();
            $total  = (int) ($params['totalItems']    ?? 0);
            $per    = (int) ($params['itemsPerPage'] ?? 50);
            if ($per <= 0 || $page * $per >= $total) { break; }
            $page++;
        }
        return $out;
    }

    
    public function fetch_one_canonical(array $vendor, $remote_id) {
        $remote_id = (string) $remote_id;
        if ($remote_id === '') { return null; }
        $full = $this->api_request($vendor, 'GET', '/orders/' . rawurlencode($remote_id), null);
        if (is_wp_error($full) || !is_array($full)) { return null; }
        return $this->normalise_order($full);
    }

    
    private function fetch_window(array $vendor, $since_ts, $until_ts) {
        $since_iso = gmdate('c', max(0, (int) $since_ts));
        $until = (int) $until_ts > 0 ? (int) $until_ts : 0;
        $page = 1;
        $orders_out = array();
        $loop_guard = 0;

        while ($loop_guard++ < 40) {
            $resp = $this->api_request($vendor, 'GET', '/orders?' . http_build_query(array(
                'page'         => $page,
                'itemsPerPage' => 50,
                'dateFrom'     => $since_iso,
            )), null);
            if (is_wp_error($resp) || !is_array($resp)) { break; }
            $list = isset($resp['orders']) && is_array($resp['orders']) ? $resp['orders'] : array();
            if (empty($list)) { break; }

            foreach ($list as $summary) {
                $oid = (string) ($summary['id'] ?? '');
                if ($oid === '') { continue; }

                
                
                
                if ($until > 0) {
                    $created_iso = (string) ($summary['createdAt'] ?? $summary['createdDate'] ?? '');
                    $created_ts  = $created_iso !== '' ? (int) strtotime($created_iso) : 0;
                    if ($created_ts > 0 && $created_ts > $until) { continue; }
                }

                $full = $this->api_request($vendor, 'GET', '/orders/' . rawurlencode($oid), null);
                if (is_wp_error($full) || !is_array($full)) { continue; }
                $orders_out[] = $this->normalise_order($full);
            }

            $params = isset($resp['params']) && is_array($resp['params']) ? $resp['params'] : array();
            $total  = (int) ($params['totalItems']    ?? 0);
            $per    = (int) ($params['itemsPerPage'] ?? 50);
            if ($per <= 0 || $page * $per >= $total) { break; }
            $page++;
        }
        return $orders_out;
    }

    
    private function normalise_order(array $sf) {
        
        
        
        
        
        
        if (isset($sf['order']) && is_array($sf['order']) && !isset($sf['id'])) {
            $sf = $sf['order'];
        }

        $addr = isset($sf['addressDetails']) ? $sf['addressDetails'] : array();
        $cust = isset($sf['customer'])       ? $sf['customer']       : array();

        $billing = array(
            'first_name' => (string) ($cust['firstName'] ?? ''),
            'last_name'  => (string) ($cust['lastName']  ?? ''),
            'phone'      => (string) ($cust['phone']     ?? ''),
            'email'      => (string) ($cust['email']     ?? ''),
            'address_1'  => trim((string) ($addr['street'] ?? '') . ' ' . (string) ($addr['streetNumber'] ?? '')),
            'city'       => (string) ($addr['city']     ?? ''),
            'postcode'   => (string) ($addr['postCode'] ?? ''),
            'state'      => (string) ($addr['regionCode'] ?? ''),
            'country'    => (string) ($addr['countryCode'] ?? 'GR'),
        );
        $shipping = $billing;

        
        
        
        
        
        
        $cents_to_eur = static function ($v) {
            return is_numeric($v) ? round(((float) $v) / 100, 2) : 0.0;
        };

        $line_items = array();
        foreach ((array) ($sf['lineItems'] ?? array()) as $li) {
            
            
            $remote_id = (string) ($li['merchantSku'] ?? $li['sku'] ?? '');
            $line_items[] = array(
                'remote_id'  => $remote_id,
                'qty'        => (int) ($li['quantity'] ?? 1),
                'unit_price' => $cents_to_eur($li['unitPrice'] ?? 0),
                'tax'        => 0.0,
                'title'      => (string) ($li['productName'] ?? ''),
            );
        }

        $carrier         = isset($sf['carrier']) && is_array($sf['carrier']) ? $sf['carrier'] : array();
        $courier_name    = (string) ($carrier['name']         ?? '');
        $delivery_name   = (string) ($carrier['deliveryName'] ?? '');
        $tracking_codes  = array();
        if (!empty($carrier['trackingCodes']) && is_array($carrier['trackingCodes'])) {
            $tracking_codes = array_map('strval', $carrier['trackingCodes']);
        }

        $invoice_payload = null;
        if (!empty($sf['hasInvoice']) && !empty($sf['invoiceDetails']) && is_array($sf['invoiceDetails'])) {
            $inv = $sf['invoiceDetails'];
            $invoice_payload = array(
                'company'    => (string) ($inv['companyName'] ?? $inv['company'] ?? ''),
                'profession' => (string) ($inv['profession']  ?? ''),
                'vat'        => (string) ($inv['vatNumber']   ?? $inv['vat'] ?? ''),
                'doy'        => (string) ($inv['doy']         ?? ''),
                'address_1'  => (string) ($inv['address']     ?? ''),
                'city'       => (string) ($inv['city']        ?? ''),
                'postcode'   => (string) ($inv['postCode']    ?? ''),
                'region'     => (string) ($inv['region']      ?? ''),
            );
        }

        
        
        
        
        
        
        
        
        $state_raw    = (string) ($sf['state'] ?? '');
        $state_lower  = strtolower($state_raw);
        $state_letter = strtoupper($state_raw);

        $event_type = 'order_updated';
        
        if ($state_letter === 'O' || $state_lower === 'registered' || $state_raw === '') {
            $event_type = 'new_order';
        }
        
        if ($state_letter === 'D'
            || $state_lower === 'declined'
            || $state_lower === 'cancelled'
            || $state_lower === 'returned'
        ) {
            $event_type = 'order_cancelled';
        }

        
        
        
        
        
        $created_at = (string) ($sf['createdAt'] ?? '');
        $created_ts = $created_at !== '' ? (int) strtotime($created_at . ' UTC') : 0;

        return array(
            'event_type'      => $event_type,
            'remote_order_id' => (string) ($sf['id']         ?? ''),
            'remote_code'     => (string) ($sf['id']         ?? ''),
            'state'           => $state_letter,
            'created_at'      => $created_ts,
            'billing'         => $billing,
            'shipping'        => $shipping,
            'line_items'      => $line_items,
            'totals'          => array(
                'shipping' => 0.0,
                'tax'      => 0.0,
                'fees'     => 0.0,
                'total'    => $cents_to_eur($sf['totalItemsAmount'] ?? 0),
            ),
            'courier'         => $courier_name !== '' ? $courier_name : $delivery_name,
            'voucher_url'     => '', 
            'tracking_codes'  => $tracking_codes,
            'invoice'         => $invoice_payload,
            'gift_wrap'       => self::any_gift_wrap_in_lines($sf['lineItems'] ?? array()),
            'raw'             => $sf,
        );
    }

    private static function any_gift_wrap_in_lines($lines) {
        if (!is_array($lines)) { return false; }
        foreach ($lines as $li) {
            if (!empty($li['giftWrap'])) { return true; }
        }
        return false;
    }

    
    private function create_and_store_voucher(array $vendor, $remote_order_id) {
        
        
        $created = $this->api_request($vendor, 'POST', '/shipments/' . rawurlencode($remote_order_id), array(
            'numberOfPackages' => 1,
            'packageComment'   => '',
        ));

        $tracking_number = is_wp_error($created) ? '' : $this->extract_tracking_number($created);

        if ($tracking_number === '') {
            
            
            
            $order_resp = $this->api_request($vendor, 'GET', '/orders/' . rawurlencode($remote_order_id), null);
            if (!is_wp_error($order_resp)) {
                $tracking_number = $this->extract_tracking_number($order_resp);
            }
        }

        if ($tracking_number === '') {
            return '';
        }

        
        
        
        $printed = $this->api_request($vendor, 'GET', '/shipments/' . rawurlencode($tracking_number) . '/print', null);
        if (is_wp_error($printed) || empty($printed['shipments']) || !is_array($printed['shipments'])) {
            return '';
        }
        $shipment = $printed['shipments'][0];
        $content = (string) ($shipment['voucherContent'] ?? '');
        $format  = (string) ($shipment['voucherFormat']  ?? 'pdf');
        if ($content === '') { return ''; }

        
        
        return AIEO_MOI_Voucher_Store::save(
            (string) $vendor['slug'],
            (string) $remote_order_id,
            $content,
            $format
        );
    }

    
    private function extract_tracking_number($resp) {
        if (!is_array($resp)) { return ''; }
        if (!empty($resp['trackingNumber'])) {
            return (string) $resp['trackingNumber'];
        }
        if (!empty($resp['shipments']) && is_array($resp['shipments'])) {
            foreach ($resp['shipments'] as $s) {
                if (!empty($s['trackingNumber'])) {
                    return (string) $s['trackingNumber'];
                }
            }
        }
        if (!empty($resp['order']['shipments']) && is_array($resp['order']['shipments'])) {
            foreach ($resp['order']['shipments'] as $s) {
                if (!empty($s['trackingNumber'])) {
                    return (string) $s['trackingNumber'];
                }
            }
        }
        return '';
    }

    
    private function api_request(array $vendor, $method, $path, $body) {
        $u = (string) ($vendor['credentials']['username'] ?? '');
        $p = (string) ($vendor['credentials']['password'] ?? '');
        if ($u === '' || $p === '') {
            return new WP_Error('no_credentials', __('Shopflix credentials missing.', 'ai-eshop-optimizer'));
        }
        $args = array(
            'method'  => strtoupper((string) $method),
            'timeout' => 20,
            'headers' => array(
                'Authorization' => 'Basic ' . base64_encode($u . ':' . $p),
                'Accept'        => 'application/json',
                'Content-Type'  => 'application/json',
            ),
        );
        if ($body !== null && $args['method'] !== 'GET') {
            $args['body'] = wp_json_encode($body);
        }
        $resp = wp_remote_request(self::API_BASE . $path, $args);
        if (is_wp_error($resp)) { return $resp; }
        $code = (int) wp_remote_retrieve_response_code($resp);
        $raw  = (string) wp_remote_retrieve_body($resp);
        if ($code === 204) { return array(); }
        $json = json_decode($raw, true);
        if ($code >= 400) {
            $msg = '';
            if (is_array($json) && isset($json['error']) && is_array($json['error'])) {
                $e = $json['error'];
                $msg = (string) ($e['message'] ?? $e['errorMessage'] ?? '');
                $ec  = (string) ($e['code'] ?? '');
                if ($msg !== '' && $ec !== '') { $msg = $msg . ' (' . $ec . ')'; }
            }
            if ($msg === '') { $msg = 'Shopflix HTTP ' . $code; }
            return new WP_Error('shopflix_api_error', $msg, array('status' => $code, 'body' => $raw));
        }
        return is_array($json) ? $json : array();
    }
}

AIEO_MOI_Provider_Registry::register(new AIEO_MOI_Provider_Shopflix());
