<?php

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

class AIEO_Courier_Driver_Speedex extends AIEO_Courier_Driver_Base {

    const ENDPOINT_TRACK = 'https://www.speedex.gr/speedex/NewTrackAndTrace.aspx';
    const ENDPOINT_SOAP  = 'https://www.speedex.gr/getvoutrans/GetVouTrans.asmx';

    public function code()  { return 'speedex'; }
    public function label() { return 'Speedex'; }

    public function capabilities() {
        return array('create', 'track');
    }

    
    public function create_mode() {
        $cfg = $this->credentials();
        return (!empty($cfg['username']) && !empty($cfg['password']) && !empty($cfg['customer_id']))
            ? 'api'
            : 'manual';
    }

    public function settings_schema() {
        return array(
            'username'      => array('type' => 'text',     'label' => __('Partner username', 'ai-eshop-optimizer'),
                                     'help'  => __('Required for SOAP voucher creation. Leave empty to keep the driver in track-only mode.', 'ai-eshop-optimizer')),
            'password'      => array('type' => 'password', 'label' => __('Partner password', 'ai-eshop-optimizer')),
            'customer_id'   => array('type' => 'text',     'label' => __('Customer ID (cust_id)', 'ai-eshop-optimizer')),
            'agreement_id'  => array('type' => 'text',     'label' => __('Agreement ID',  'ai-eshop-optimizer')),
            'branch_id'     => array('type' => 'text',     'label' => __('Enter branch ID', 'ai-eshop-optimizer')),
            'voucher_type'  => array('type' => 'number',   'label' => __('Voucher type (GetNumbers `type` param)', 'ai-eshop-optimizer'),
                                     'help'  => __('Defaults to 1. Speedex partner contract decides what type code to use.', 'ai-eshop-optimizer')),
            'pay_code_flag' => array('type' => 'number',   'label' => __('Default PayCode_Flag', 'ai-eshop-optimizer'),
                                     'help'  => __('0 = sender pays, 1 = recipient pays (consult Speedex partner manual).', 'ai-eshop-optimizer')),
        );
    }

    public function tracking_url($voucher_no) {
        return AIEO_Runtime_Fulfillment_URLs::tracking_url('speedex', (string) $voucher_no);
    }

    public function map_status($raw_code) {
        $raw = mb_strtoupper((string) $raw_code);
        if ($raw === '') { return 'unknown'; }
        if (mb_strpos($raw, 'ΠΡΟΣ ΠΑΡΑΔΟΣΗ')   !== false) { return 'out_for_delivery'; }
        if (mb_strpos($raw, 'ΠΡΟΣ ΔΙΑΝΟΜΗ')    !== false) { return 'out_for_delivery'; }
        if (mb_strpos($raw, 'ΕΞΟΔΟΣ')          !== false) { return 'out_for_delivery'; }
        if (mb_strpos($raw, 'ΠΑΡΑΔΟΘ')         !== false) { return 'delivered'; }
        if (mb_strpos($raw, 'ΕΠΙΣΤΡΟΦ')        !== false) { return 'returned'; }
        if (mb_strpos($raw, 'ΑΚΥΡΩΣ')          !== false) { return 'canceled'; }
        if (mb_strpos($raw, 'ΑΠΟΠΕΙΡ')         !== false) { return 'attempted'; }
        if (mb_strpos($raw, 'ΠΑΡΑΛΑΒ')         !== false) { return 'in_transit'; }
        if (mb_strpos($raw, 'ΑΠΟΣΤΟΛ')         !== false) { return 'in_transit'; }
        if (mb_strpos($raw, 'ΔΡΟΜΟΛΟΓ')        !== false) { return 'in_transit'; }
        return 'unknown';
    }

    
    public function create_voucher(array $payload) {
        if ($this->create_mode() === 'manual') {
            return $this->create_voucher_manual($payload);
        }
        return $this->create_voucher_api($payload);
    }

    
    private function create_voucher_manual(array $payload) {
        $voucher_no = trim((string) ($payload['manual_voucher_no'] ?? $payload['voucher_no'] ?? ''));
        if ($voucher_no === '') {
            return array('ok' => false, 'error' => __('Tracking number required.', 'ai-eshop-optimizer'));
        }
        $sanitized = preg_replace('/[^0-9]/', '', $voucher_no);
        if (strlen($sanitized) !== 12) {
            return array('ok' => false, 'error' => __('Speedex tracking numbers must be exactly 12 digits.', 'ai-eshop-optimizer'));
        }
        return array('ok' => true, 'voucher_no' => $sanitized, 'subvouchers' => array(), 'job_id' => null);
    }

    
    private function create_voucher_api(array $payload) {
        $cfg = $this->credentials();
        $client = $this->soap_client();
        if ($client instanceof WP_Error) { return array('ok' => false, 'error' => $client->get_error_message()); }

        
        try {
            $get = $client->GetNumbers(array(
                'type'            => (int) ($cfg['voucher_type'] ?? 1),
                'inpId'           => 0,
                'customerCode'    => (string) ($cfg['customer_id'] ?? ''),
                'totalNum'        => '1',
                'VoucherToExists' => '',
            ));
        } catch (\SoapFault $e) {
            return array('ok' => false, 'error' => 'GetNumbers SOAP fault: ' . $e->getMessage());
        }
        $get_result = $get->GetNumbersResult ?? null;
        if (!$get_result) {
            $msg = isset($get->retmessage) ? (string) $get->retmessage : 'Speedex GetNumbers returned false';
            return array('ok' => false, 'error' => $msg);
        }
        $voucher_no = isset($get->voucherFrom) ? trim((string) $get->voucherFrom) : '';
        $reserved_id = isset($get->id) ? (int) $get->id : 0;
        if ($voucher_no === '') {
            return array('ok' => false, 'error' => 'Speedex GetNumbers did not return a voucher number.');
        }

        
        $recipient = isset($payload['recipient']) && is_array($payload['recipient']) ? $payload['recipient'] : array();

        $services_csv = strtoupper((string) ($payload['services_csv'] ?? ''));
        $express_delivery = (int) (strpos($services_csv, 'EXPRESS') !== false ? 1 : 0);
        $saturday_delivery = (int) (strpos($services_csv, 'SAT') !== false ? 1 : 0);

        $pod_record = array(
            'voucher_code'         => $voucher_no,
            'EnterBranchId'        => (string) ($cfg['branch_id']    ?? ''),
            'SND_Customer_Id'      => (string) ($cfg['customer_id']  ?? ''),
            'Snd_agreement_id'     => (string) ($cfg['agreement_id'] ?? ''),
            'RCV_Afm'              => (string) ($recipient['vat']     ?? ''),
            'RCV_DOY'              => (string) ($recipient['tax_office'] ?? ''),
            'RCV_Company'          => (string) ($recipient['company'] ?? ''),
            'RCV_Name'             => (string) ($recipient['name']    ?? ''),
            'RCV_Addr1'            => (string) ($recipient['address'] ?? ''),
            'RCV_Addr2'            => '',
            'RCV_Zip_Code'         => (string) ($recipient['zip']     ?? ''),
            'RCV_City'             => (string) ($recipient['city']    ?? ''),
            'RCV_Country'          => (string) ($recipient['country'] ?? 'GR'),
            'RCV_Tel1'             => (string) ($recipient['phone']   ?? ''),
            'RCV_Tel2'             => '',
            'Voucher_Weight'       => (float) ($payload['weight']       ?? 0.5),
            'Pod_Amount_Cash'      => (float) ($payload['cod_amount']   ?? 0),
            'Security_Value'       => (int)   ($payload['ins_amount']   ?? 0),
            'Express_Delivery'     => $express_delivery,
            'Saturday_Delivery'    => $saturday_delivery,
            'Time_Limit'           => (string) ($payload['time_limit']  ?? ''),
            'Comments_2853_1'      => '',
            'Comments_2853_2'      => '',
            'Comments_2853_3'      => '',
            'Comments'             => (string) ($payload['comments']    ?? ''),
            'Voucher_Volume'       => (float) ($payload['volume']       ?? 0),
            'Pod_Amount_Description' => '',
            'PayCode_Flag'         => (int)   ($cfg['pay_code_flag']    ?? 0),
            'BranchBankCode'       => '',
            'Paratiriseis_2853_1'  => '',
            'Paratiriseis_2853_2'  => '',
            'Paratiriseis_2853_3'  => '',
            'email'                => (string) ($recipient['email']     ?? ''),
            'BasicService'         => '',
            'Items'                => max(1, (int) ($payload['pieces']  ?? 1)),
            'Vouc_descr'           => (string) ($payload['content_description'] ?? ''),
            'Comments_new'         => '',
        );

        try {
            $insert = $client->insertPodData_List(array(
                'username'     => (string) $cfg['username'],
                'password'     => (string) $cfg['password'],
                '_myInListPod' => array('podData2' => $pod_record),
                '_tableFlag'   => 1,
            ));
        } catch (\SoapFault $e) {
            return array('ok' => false, 'error' => 'insertPodData_List SOAP fault: ' . $e->getMessage());
        }

        $insert_result = isset($insert->insertPodData_ListResult) ? (string) $insert->insertPodData_ListResult : '';
        
        
        
        $is_error = ($insert_result === '' || stripos($insert_result, 'ERR') === 0 || mb_stripos($insert_result, 'Σφάλμα') === 0);
        if ($is_error) {
            return array('ok' => false, 'error' => 'Speedex insertPodData_List: ' . $insert_result);
        }

        return array(
            'ok'           => true,
            'voucher_no'   => $voucher_no,
            'subvouchers'  => array(),
            'job_id'       => $reserved_id,
            'raw_response' => $insert_result,
        );
    }

    public function track($voucher_no) {
        $voucher_no = preg_replace('/[^0-9]/', '', (string) $voucher_no);
        if ($voucher_no === '') {
            return array('ok' => false, 'error' => 'voucher_no required');
        }

        $url = self::ENDPOINT_TRACK . '?number=' . rawurlencode($voucher_no);
        $resp = wp_remote_get($url, array(
            'timeout'     => 20,
            'redirection' => 2,
            'headers'     => array('Accept' => 'text/html,application/xhtml+xml'),
        ));
        if (is_wp_error($resp)) { return array('ok' => false, 'error' => $resp->get_error_message()); }
        $code = (int) wp_remote_retrieve_response_code($resp);
        if ($code !== 200) {
            
            return array('ok' => false, 'error' => sprintf(__('Speedex HTTP %d', 'ai-eshop-optimizer'), $code));
        }
        $html = (string) wp_remote_retrieve_body($resp);
        if ($html === '') {
            return array('ok' => false, 'error' => __('Speedex: empty response', 'ai-eshop-optimizer'));
        }
        if (stripos($html, 'alert-warning') !== false) {
            return array('ok' => false, 'error' => __('Speedex: tracking number not found', 'ai-eshop-optimizer'));
        }

        $checkpoints = $this->scrape_timeline($html);
        if (empty($checkpoints)) {
            return array('ok' => true, 'status_code' => '', 'checkpoints' => array());
        }

        $last         = end($checkpoints);
        $latest_code  = (string) ($last['code'] ?? '');
        $delivered_at = ($this->map_status($latest_code) === 'delivered' && !empty($last['checkpoint_at']))
            ? (int) $last['checkpoint_at']
            : null;

        return array(
            'ok'           => true,
            'status_code'  => $latest_code,
            'checkpoints'  => $checkpoints,
            'consignee'    => null,
            'delivered_at' => $delivered_at,
        );
    }

    

    private function credentials() {
        if (!class_exists('AIEO_Fulfillment_Settings')) { return array(); }
        $cfg = AIEO_Fulfillment_Settings::get('courier_speedex', array());
        return is_array($cfg) ? $cfg : array();
    }

    
    private function soap_client() {
        static $cache = null;
        if ($cache !== null) { return $cache; }
        if (!class_exists('SoapClient')) {
            return new WP_Error('soap_missing', __('PHP SOAP extension not available — install php-soap to use the Speedex partner API.', 'ai-eshop-optimizer'));
        }
        try {
            $cache = new SoapClient(self::ENDPOINT_SOAP . '?WSDL', array(
                'soap_version'       => SOAP_1_1,
                'connection_timeout' => 15,
                'cache_wsdl'         => WSDL_CACHE_BOTH,
                'trace'              => false,
                'exceptions'         => true,
                'keep_alive'         => true,
            ));
        } catch (\SoapFault $e) {
            
            return new WP_Error('soap_init', sprintf(__('Could not init Speedex SoapClient: %s', 'ai-eshop-optimizer'), $e->getMessage()));
        }
        return $cache;
    }

    
    private function scrape_timeline($html) {
        if (!class_exists('DOMDocument') || !class_exists('DOMXPath')) { return array(); }

        $doc  = new DOMDocument();
        $prev = libxml_use_internal_errors(true);
        $doc->loadHTML('<?xml encoding="UTF-8">' . $html);
        libxml_clear_errors();
        libxml_use_internal_errors($prev);

        $xpath = new DOMXPath($doc);
        $cards = $xpath->query('//div[contains(concat(" ", normalize-space(@class), " "), " timeline-card ")]');
        if (!$cards || $cards->length === 0) { return array(); }

        $out = array();
        foreach ($cards as $card) {
            $span_nodes  = $xpath->query('.//span[contains(concat(" ", normalize-space(@class), " "), " font-small-3 ")]', $card);
            $title_nodes = $xpath->query('.//h4[contains(concat(" ", normalize-space(@class), " "), " card-title ")]', $card);
            if (!$span_nodes || !$title_nodes || $span_nodes->length === 0 || $title_nodes->length === 0) { continue; }

            $location_line = trim((string) $span_nodes->item(0)->textContent);
            $title         = trim((string) $title_nodes->item(0)->textContent);
            if ($title === '') { continue; }

            $parts    = explode(',', $location_line, 2);
            $location = trim($parts[0]);
            $when_str = isset($parts[1]) ? trim($parts[1]) : '';
            $ts       = null;
            if ($when_str !== '' && preg_match('#(\d{2}/\d{2}/\d{4}).*?(\d{2}:\d{2})#', $when_str, $m)) {
                $dt = DateTime::createFromFormat('d/m/Y H:i', $m[1] . ' ' . $m[2]);
                if ($dt) { $ts = $dt->getTimestamp(); }
            }

            $out[] = array(
                'code'          => $title,
                'description'   => $title,
                'location'      => $location,
                'checkpoint_at' => is_int($ts) ? $ts : null,
            );
        }
        return $out;
    }
}

add_filter('aieo_fulfillment_couriers', static function (array $drivers) {
    if (!isset($drivers['speedex']) && class_exists('AIEO_Courier_Driver_Speedex')) {
        $drivers['speedex'] = new AIEO_Courier_Driver_Speedex();
    }
    return $drivers;
});
