<?php

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

class AIEO_Courier_Driver_ACS extends AIEO_Courier_Driver_Base {

    const ENDPOINT_LIVE = 'https://webservices.acscourier.net/ACSRestServices/api/ACSAutoRest';

    public function code()  { return 'acs'; }
    public function label() { return 'ACS Courier'; }

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

    public function settings_schema() {
        return array(
            'company_id'          => array('type' => 'text',     'label' => __('Company ID',          'ai-eshop-optimizer'), 'required' => true),
            'company_password'    => array('type' => 'password', 'label' => __('Company password',    'ai-eshop-optimizer'), 'required' => true),
            'user_id'             => array('type' => 'text',     'label' => __('User ID',             'ai-eshop-optimizer'), 'required' => true),
            'user_password'       => array('type' => 'password', 'label' => __('User password',       'ai-eshop-optimizer'), 'required' => true),
            'api_key'             => array('type' => 'password', 'label' => __('API key (AcsApiKey)', 'ai-eshop-optimizer'), 'required' => true,
                                           'help'  => __('Sent as the AcsApiKey header.', 'ai-eshop-optimizer')),
            'billing_code'        => array('type' => 'text',     'label' => __('Billing code',        'ai-eshop-optimizer'), 'required' => true),
            'sender_name'         => array('type' => 'text',     'label' => __('Sender name',         'ai-eshop-optimizer'), 'required' => true),
            'default_paper'       => array('type' => 'select',   'label' => __('Default paper size',  'ai-eshop-optimizer'),
                                           'options' => array('A4' => 'A4', 'THERMAL' => 'Thermal')),
            'default_charge'      => array('type' => 'select',   'label' => __('Charge to',           'ai-eshop-optimizer'),
                                           'options' => array('1' => __('Sender', 'ai-eshop-optimizer'),
                                                              '2' => __('Recipient', 'ai-eshop-optimizer'))),
            'enable_rdo'          => array('type' => 'checkbox', 'label' => __('Enable RDO (return of documents)', 'ai-eshop-optimizer')),
            'enable_rec'          => array('type' => 'checkbox', 'label' => __('Enable REC (return of receipt)',   'ai-eshop-optimizer')),
            'enable_saturday'     => array('type' => 'checkbox', 'label' => __('Enable SAT (Saturday delivery)',   'ai-eshop-optimizer')),
        );
    }

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

    
    protected function code_map() {
        return array(
            'ΠΑΡΑΔΟΣΗ'                      => 'delivered',
            'ΠΑΡΑΛΑΒΗ ΑΠΟ ACS'              => 'in_transit',
            'ΑΠΟΣΤΟΛΗ'                      => 'in_transit',
            'ΔΡΟΜΟΛΟΓΗΣΗ'                   => 'in_transit',
            'ΠΡΟΣ ΠΑΡΑΔΟΣΗ'                 => 'out_for_delivery',
            'ΕΠΙΣΤΡΟΦΗ'                     => 'returned',
            'ΑΚΥΡΩΣΗ'                       => 'canceled',
            'ΑΠΟΠΕΙΡΑ ΠΑΡΑΔΟΣΗΣ'            => 'attempted',
            'ΛΑΘΟΣ ΔΙΕΥΘΥΝΣΗ'               => 'attempted',
            'ΑΠΟΥΣΙΑ ΠΑΡΑΛΗΠΤΗ'             => 'attempted',
            'ΑΡΝΗΣΗ ΠΑΡΑΛΑΒΗΣ'              => 'attempted',
            'ΕΛΛΕΙΨΗ ΧΡΗΜΑΤΩΝ'              => 'attempted',
            'ΦΟΡΤΩΣΗ'                       => 'in_transit',
            'ΕΚΦΟΡΤΩΣΗ'                     => 'in_transit',
            'ΑΦΙΞΗ ΣΕ ΣΗΜΕΙΟ'               => 'in_transit',
            'ΕΞΟΔΟΣ ΑΠΟ ΣΗΜΕΙΟ'             => 'in_transit',
        );
    }

    
    public function authenticate(array $creds) {
        $creds = array_merge($this->credentials(), $creds);
        $missing = array();
        foreach (array('company_id', 'company_password', 'user_id', 'user_password', 'api_key') as $req) {
            if (empty($creds[$req])) { $missing[] = $req; }
        }
        if (!empty($missing)) {
            return array(
                'ok'    => false,
                
                'error' => sprintf(__('ACS credentials missing: %s', 'ai-eshop-optimizer'), implode(', ', $missing)),
            );
        }
        return array('ok' => true, 'auth_token' => null, 'expires_at' => null);
    }

    
    public function create_voucher(array $payload) {
        $auth = $this->authenticate(array());
        if (!$auth['ok']) { return $auth; }

        $cfg       = $this->credentials();
        $recipient = isset($payload['recipient']) && is_array($payload['recipient']) ? $payload['recipient'] : array();

        
        
        

        
        
        
        
        
        
        
        $addr_raw  = trim((string) ($recipient['address'] ?? ''));
        $addr_no   = '';
        $addr_line = $addr_raw;
        if ($addr_raw !== '' && preg_match('/^(.*?)[\s,]+([0-9]+[A-Za-zΑ-Ωα-ω]?)\s*$/u', $addr_raw, $m)) {
            $addr_line = trim($m[1]);
            $addr_no   = trim($m[2]);
        }

        
        
        
        
        
        
        
        $phone_raw  = (string) ($recipient['phone'] ?? '');
        $phone_norm = preg_replace('/\D+/', '', $phone_raw);
        if ($phone_norm !== '' && strpos($phone_norm, '0030') === 0) { $phone_norm = substr($phone_norm, 4); }
        if ($phone_norm !== '' && strpos($phone_norm, '30') === 0 && strlen($phone_norm) === 12) { $phone_norm = substr($phone_norm, 2); }
        $phone_land = '';
        $phone_cell = '';
        if ($phone_norm !== '' && strlen($phone_norm) === 10) {
            if ($phone_norm[0] === '6') {
                $phone_cell = $phone_norm;
            } else {
                $phone_land = $phone_norm;
            }
        } else {
            
            
            
            $phone_land = $phone_norm;
        }

        
        
        
        
        
        $cod_amount = (float) ($payload['cod_amount'] ?? 0);
        $default_charge = (string) ($cfg['default_charge'] ?? '');
        if ($default_charge === '') { $default_charge = $cod_amount > 0 ? '4' : '2'; }
        $charge_type = (string) ($payload['charge'] ?? $default_charge);
        if ($charge_type === '') { $charge_type = $cod_amount > 0 ? '4' : '2'; }

        
        
        
        
        
        
        $services_csv = (string) ($payload['services_csv'] ?? '');
        if ($cod_amount > 0) {
            $tokens = array_filter(array_map('trim', explode(',', strtoupper($services_csv))));
            if (!in_array('COD', $tokens, true)) {
                $tokens[] = 'COD';
                $services_csv = implode(',', $tokens);
            }
        }

        $params = array(
            'Company_ID'              => (string) $cfg['company_id'],
            'Company_Password'        => (string) $cfg['company_password'],
            'User_ID'                 => (string) $cfg['user_id'],
            'User_Password'           => (string) $cfg['user_password'],
            'Billing_Code'            => (string) $cfg['billing_code'],
            'Pickup_Date'             => isset($payload['pickup_date'])  ? (string) $payload['pickup_date']  : gmdate('Y-m-d'),
            'Sender'                  => (string) $cfg['sender_name'],
            'Recipient_Name'          => (string) ($recipient['name']    ?? ''),
            'Recipient_Address'       => $addr_line,
            'Recipient_Address_Number'=> $addr_no,
            'Recipient_Zipcode'       => (string) ($recipient['zip']     ?? ''),
            'Recipient_Region'        => (string) ($recipient['city']    ?? ''),
            'Recipient_Phone'         => $phone_land,
            'Recipient_Cell_Phone'    => $phone_cell,
            'Recipient_Country'       => (string) ($recipient['country'] ?? 'GR'),
            'Charge_Type'             => $charge_type,
            'Item_Quantity'           => max(1, (int) ($payload['pieces']  ?? 1)),
            
            
            
            
            
            
            'Weight'                  => (float) ($payload['weight']     ?? 0.5),
            'Cod_Ammount'             => (float) ($payload['cod_amount'] ?? 0),
            'Acs_Delivery_Products'   => $this->build_services_string($services_csv),
            'Reference_Key1'          => (string) ($payload['reference_1'] ?? ''),
            'Reference_Key2'          => (string) ($payload['reference_2'] ?? ''),
        );
        if (!empty($payload['content_type_id'])) {
            $params['Content_Type_ID'] = (string) $payload['content_type_id'];
        }
        if (!empty($payload['content_description'])) {
            $params['Content_Type_Description'] = (string) $payload['content_description'];
        }

        $resp = $this->post('ACS_Create_Voucher', $params);
        if (is_wp_error($resp)) {
            return array('ok' => false, 'error' => $resp->get_error_message());
        }

        $value_output = $this->extract_value_output($resp);
        if (empty($value_output['Voucher_No'])) {
            
            
            
            
            
            
            $row_msg = isset($value_output['Error_Message']) ? trim((string) $value_output['Error_Message']) : '';
            $top_err = $resp['ACSExecution_HasError'] ?? false;
            $top_msg = isset($resp['ACSExecutionErrorMessage']) ? trim((string) $resp['ACSExecutionErrorMessage']) : '';

            if ($row_msg !== '') {
                $shown = $row_msg;
            } elseif ($top_err && $top_msg !== '') {
                $shown = $top_msg;
            } else {
                $shown = (string) __('No voucher number in response', 'ai-eshop-optimizer');
            }

            
            
            
            
            $safe_params = $params;
            foreach (array('Company_Password', 'User_Password') as $secret) {
                if (isset($safe_params[$secret])) { $safe_params[$secret] = '***'; }
            }
            error_log('[AIEO-ACS-CREATE-FAIL] params=' . wp_json_encode($safe_params) . ' response=' . wp_json_encode($resp));
            return array('ok' => false, 'error' => $shown, 'raw' => $resp);
        }

        return array(
            'ok'          => true,
            'voucher_no'  => (string) $value_output['Voucher_No'],
            'subvouchers' => array(),
            'job_id'      => null,
            'raw'         => $resp,
        );
    }

    
    public function get_label_pdf($voucher_no, $format = 'A4') {
        $auth = $this->authenticate(array());
        if (!$auth['ok']) { return $auth; }

        $cfg = $this->credentials();
        $print_type = (strtoupper($format) === 'THERMAL') ? 1 : 2; 

        
        
        
        
        
        
        
        $resp = $this->post('ACS_Print_Voucher', array(
            'Company_ID'       => (string) $cfg['company_id'],
            'Company_Password' => (string) $cfg['company_password'],
            'User_ID'          => (string) $cfg['user_id'],
            'User_Password'    => (string) $cfg['user_password'],
            'Voucher_No'       => (string) $voucher_no,
            'Print_Type'       => $print_type,
            'Start_Position'   => 1,
        ));
        if (is_wp_error($resp)) { return array('ok' => false, 'error' => $resp->get_error_message()); }

        $value_output = $this->extract_value_output($resp);
        $b64 = '';
        if (!empty($value_output['ACSObjectOutput'])) {
            $raw = $value_output['ACSObjectOutput'];
            
            
            if (is_string($raw)) {
                $b64 = $raw;
            } elseif (is_array($raw)) {
                $first = reset($raw);
                if (is_string($first)) { $b64 = $first; }
            }
        }
        if ($b64 === '') {
            $err = $resp['ACSExecution_HasError'] ?? false;
            $msg = $resp['ACSExecutionErrorMessage'] ?? '';
            if ($msg === '') { $msg = 'No PDF in ACS print response'; }
            error_log('[AIEO-ACS-PRINT-FAIL] voucher=' . $voucher_no . ' has_error=' . ($err ? '1' : '0') . ' msg="' . $msg . '" response=' . substr(wp_json_encode($resp), 0, 800));
            return array('ok' => false, 'error' => (string) $msg, 'raw' => $resp);
        }

        $pdf_bytes = base64_decode($b64, true);
        if ($pdf_bytes === false || substr((string) $pdf_bytes, 0, 4) !== '%PDF') {
            error_log('[AIEO-ACS-PRINT-FAIL] voucher=' . $voucher_no . ' base64 decode failed or not a PDF (got ' . strlen((string) $pdf_bytes) . ' bytes)');
            return array('ok' => false, 'error' => 'ACS returned non-PDF payload', 'raw' => $resp);
        }

        
        
        return array('ok' => true, 'pdf' => $pdf_bytes, 'pdf_url' => null);
    }

    public function cancel($voucher_no) {
        $auth = $this->authenticate(array());
        if (!$auth['ok']) { return $auth; }

        $cfg = $this->credentials();
        
        
        
        
        $resp = $this->post('ACS_Delete_Voucher', array(
            'Company_ID'       => (string) $cfg['company_id'],
            'Company_Password' => (string) $cfg['company_password'],
            'User_ID'          => (string) $cfg['user_id'],
            'User_Password'    => (string) $cfg['user_password'],
            'Language'         => null,
            'Voucher_No'       => (string) $voucher_no,
        ));
        if (is_wp_error($resp)) { return array('ok' => false, 'error' => $resp->get_error_message()); }

        if (!empty($resp['ACSExecution_HasError'])) {
            return array('ok' => false, 'error' => (string) ($resp['ACSExecutionErrorMessage'] ?? 'cancel_failed'));
        }
        return array('ok' => true);
    }

    public function track($voucher_no) {
        $auth = $this->authenticate(array());
        if (!$auth['ok']) { return $auth; }

        $cfg = $this->credentials();
        $resp = $this->post('ACS_Trackingsummary', array(
            'Company_ID'       => (string) $cfg['company_id'],
            'Company_Password' => (string) $cfg['company_password'],
            'User_ID'          => (string) $cfg['user_id'],
            'User_Password'    => (string) $cfg['user_password'],
            'Voucher_No'       => (string) $voucher_no,
            'Language'         => 'GR',
        ));
        if (is_wp_error($resp)) { return array('ok' => false, 'error' => $resp->get_error_message()); }

        $rows = $this->extract_table_output($resp);
        $checkpoints = array();
        $latest_code = '';
        $consignee   = null;
        $delivered_at = null;

        foreach ($rows as $row) {
            $action = trim((string) ($row['checkpoint_action']    ?? ''));
            $loc    = trim((string) ($row['checkpoint_location']  ?? ''));
            $notes  = trim((string) ($row['checkpoint_notes']     ?? ''));
            $when   = trim((string) ($row['checkpoint_date_time'] ?? ''));
            $ts     = $when !== '' ? strtotime($when) : null;

            $checkpoints[] = array(
                'code'          => $action,
                'description'   => $notes !== '' ? $notes : $action,
                'location'      => $loc,
                'checkpoint_at' => is_int($ts) ? $ts : null,
            );

            if ($action !== '') { $latest_code = $action; }
            if ($action === 'ΠΑΡΑΔΟΣΗ' && is_int($ts)) {
                $delivered_at = $ts;
                if ($consignee === null && $notes !== '') { $consignee = $notes; }
            }
        }

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

    

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

    
    private function post($alias, array $params) {
        $cfg = $this->credentials();
        if (empty($cfg['api_key'])) {
            return new WP_Error('acs_no_api_key', __('AcsApiKey missing in settings.', 'ai-eshop-optimizer'));
        }
        $body = array(
            'ACSAlias'             => (string) $alias,
            'ACSInputParameters'   => $params,
        );
        $resp = wp_remote_post(self::ENDPOINT_LIVE, array(
            'timeout'     => 30,
            'redirection' => 0,
            'headers'     => array(
                'AcsApiKey'    => (string) $cfg['api_key'],
                'Content-Type' => 'application/json',
                'Accept'       => 'application/json',
            ),
            'body'        => wp_json_encode($body),
        ));
        if (is_wp_error($resp)) { return $resp; }
        $code = (int) wp_remote_retrieve_response_code($resp);
        if ($code !== 200) {
            
            return new WP_Error('acs_http', sprintf(__('ACS HTTP %d', 'ai-eshop-optimizer'), $code));
        }
        $payload = json_decode((string) wp_remote_retrieve_body($resp), true);
        if (!is_array($payload)) { return new WP_Error('acs_payload', __('ACS returned non-JSON.', 'ai-eshop-optimizer')); }
        
        
        
        
        
        
        
        return $payload;
    }

    
    private function extract_value_output(array $resp) {
        $output = array();
        if (isset($resp['ACSOutputResponce']['ACSValueOutput']) && is_array($resp['ACSOutputResponce']['ACSValueOutput'])) {
            $output = $resp['ACSOutputResponce']['ACSValueOutput'];
        } elseif (isset($resp['ACSValueOutput']) && is_array($resp['ACSValueOutput'])) {
            $output = $resp['ACSValueOutput'];
        }
        if (empty($output)) { return array(); }
        $first = reset($output);
        return is_array($first) ? $first : array();
    }

    
    private function extract_table_output(array $resp) {
        $table = array();
        if (isset($resp['ACSOutputResponce']['ACSTableOutput']) && is_array($resp['ACSOutputResponce']['ACSTableOutput'])) {
            $table = $resp['ACSOutputResponce']['ACSTableOutput'];
        } elseif (isset($resp['ACSTableOutput']) && is_array($resp['ACSTableOutput'])) {
            $table = $resp['ACSTableOutput'];
        }
        if (empty($table)) { return array(); }
        $td = isset($table['Table_Data']) ? $table['Table_Data'] : array();
        return is_array($td) ? $td : array();
    }

    
    private function build_services_string($services_csv) {
        $services_csv = trim((string) $services_csv);
        if ($services_csv === '') { return ''; }
        $parts = array_filter(array_map('trim', explode(',', strtoupper($services_csv))));
        $allowed = array('SAT', 'RDO', 'REC', 'COD', 'CEC', 'CECF');
        $kept = array();
        foreach ($parts as $p) {
            if (in_array($p, $allowed, true)) { $kept[] = $p; }
        }
        return implode('|', $kept);
    }
}

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