<?php
/**
 * 哲盟DHL-TH 接口
 */
class Service_DHLTHApiProcess
{
    protected $_scheme = 'http';
    protected $_host = '113.105.65.70';
    protected $_port = '8080';
    protected $_service = '/dhl_cust/cust_dhlServlet';
    //测试账号
    //protected $_clno = '910404';
    //protected $_authorizationNO = '888888';
    //正式账号
    //protected $_clno = '913089';
    //protected $_authorizationNO = 'E6B4-V5HK-JNDW-E6V9';
    protected $_clno;
    protected $_authorizationNO;
    protected $_pdfPath;
    protected $_pdfFileName;
    protected $_orderCode;
    protected $_trackingNumber;
    protected $_error = array();
    protected $_warming = array();//用于不退出事务
    protected $_requestData;
    protected $_env = 'development';

    public function __construct()
    {
        $this->setEnv();
        $this->setAuth();
        $path = dirname( APPLICATION_PATH ). '/data/pdf/DHLTH';
        $this->setPdfPath( $path );
    }
    public function setEnv() {
        $config = Zend_Registry::get('config');
        if( isset( $config->env ) ) {
            $this->_env = $config->env;
        }
    }
    public function setAuth() {
        $auth = array(
            'development' => array(
                'clno' => '910404',
                'authorizationNO' => '888888'
            ),
            'test' => array(
                'clno' => '910404',
                'authorizationNO' => '888888'
            ),
            'product' => array(
                'clno' => '913089',
                'authorizationNO' => 'E6B4-V5HK-JNDW-E6V9'
            ),
        );
        if( isset( $auth[ $this->_env ] ) ) {
            $this->_clno            = $auth[ $this->_env ]['clno'];
            $this->_authorizationNO = $auth[ $this->_env ]['authorizationNO'];
        } else {
            throw new Exception('系统环境错误');
        }
    }
    /* @todo:设置PDF保存路径
     *
     */
    public function setPdfPath( $path )
    {
        if( !$path || is_file( $path ) )
            return;
        if( false === file_exists( $path ) ) {
            if( false === mkdir( $path, 755, true ) )
                throw new Exception('创建PDF保存路径失败');
        }
        $this->_pdfPath = $path;
    }
    protected function addError( $error ) {
        $this->_error[] = $error;
    }
    public function getError() {
        return $this->_error;
    }
    protected function addWarming( $warming ) {
        $this->_warming[] = $warming;
    }
    public function getWarming() {
        return $this->_warming;
    }
    public  function getPdfPath() {
        return $this->_pdfPath.DIRECTORY_SEPARATOR.$this->_pdfFileName;
    }
    //获取需要发票的国家
    public static function getNeedInvoiceCountry() {
        //如果哲盟那边返回这个错误提示，就说明这个国家不支持无纸化
        //Paperless shipment service is not allowed for one of these reasons: Shipper or receiver country doesn't support Paperless Service, the product selected doesn't support Paperless or the declared value entered is greater than the allowed limit. Please contact DHL representative for further information or resubmit as regular shipment.,
        return array(1,3,36,64,71,88,92,109,110,114,120,122,128,154,160,162,183,184,197,208,211,216,220,244,245,250);
    }
    //获取发票抬头
    public static function getInvoiceTitle( $hubin ) {
        $address = array(
            'A01' => array(
                'company'=>'Oceanpac c/o A To Z Online Services',
                'address'=>'71 Alps Avenue #01-02 ,SINGAPORE 498745',
                'country'=>'SINGAPORE'
            ),
            'DH2' => array(
                'company'=>'A-Z ONLINE SERVICES PTE LTD',
                'address'=>'71 Alps Avenue #01-02 ,SINGAPORE 498745',
                'country'=>'SINGAPORE'
            ),
            'DH6' => array(
                'company'=>'SKYPOST PTE LTD,',
                'address'=>'71 Alps Avenue #01-02,SINGAPORE 498745',
                'country'=>'SINGAPORE'
            ),
        );
        return isset( $address[$hubin] ) ?  $address[$hubin] : array();
    }
    public static function getHubIn( $countryName ) {
        /*$countries = array(
            'A01'=>array('澳大利亚','新西兰'),
            'DH2'=>array('美国','加拿大','墨西哥','奥地利','比利时','克罗地亚','捷克','丹麦','芬兰','法国','德国','希腊','匈牙利','冰岛','爱尔兰','意大利','列支敦士登','立陶宛','卢森堡','摩纳哥','荷兰','挪威','波兰','葡萄牙','西班牙','瑞典','瑞士','土耳其','英国','罗马尼亚','黑山共和国','塞尔维亚','格鲁吉亚','阿尔巴尼亚','安道尔','亚美尼亚','阿塞拜疆','白俄罗斯','波斯尼亚和黑塞哥维那','保加利亚','加那利群岛','塞浦路斯','爱沙尼亚','福克兰群岛','法罗群岛','直布罗陀','格陵兰岛','根西岛','以色列','泽西岛','哈萨克斯坦','科索沃','吉尔吉斯斯坦','拉脱维亚','马其顿','马耳他','摩尔多瓦','圣马力诺','斯洛伐克','斯洛文尼亚','塔吉克斯坦','乌克兰','乌兹别克斯坦'),
            'DH6'=>array('韩国','印度尼西亚','印度','孟加拉','不丹','柬埔寨','库克群岛','东帝汶','斐济','基里巴斯','老挝','马尔代夫','蒙古','缅甸','瑙鲁','尼泊尔','新喀里多尼亚','纽埃岛','朝鲜','巴基斯坦','巴布亚新几内亚','萨摩亚群岛','所罗门群岛','斯里兰卡','塔希提岛','汤加','图瓦卢','瓦努阿图','阿富汗','阿尔及利亚','巴林','埃及','伊朗','伊拉克','约旦','科威特','黎巴嫩','利比亚','毛利塔尼亚','摩洛哥','阿曼','卡塔尔','沙特阿拉伯','南非','叙利亚','突尼斯','阿拉伯联合酋长国','也门')
        );*/
        $countries = array(
            'A01'=>array('AU','NZ'),
            'DH2'=>array('US','CA','MX','AT','BE','HR','CZ','DK','FI','FR','DE','GR','HU','IS','IE','IT','LI','LT','LU','MC','NL','NO','PL','PT','ES','SE','CH','TR','GB','RO','ME','RS','GE','AL','AD','AM','AZ','BY','BA','BG','IC','CY','EE','FK','FO','GI','GL','根西岛','IL','JE','KZ','KV','KG','LV','MK','MT','MD','SM','SK','SI','TJ','UA','UZ'),
            'DH6'=>array('KR','ID','IN','BD','BT','KH','CK','TL','FJ','KI','LA','MV','MN','MM','NR','NP','NC','NU','KP','PK','PG','AS','SB','LK','塔希提岛','TO','TV','VU','AF','DZ','BH','EG','IR','IQ','JO','KW','LB','LY','MR','MA','OM','QA','SA','ZA','SY','TN','AE','YE')
        );
        $hubin = '';
        foreach( $countries as $key=>$value ) {
            if( in_array( $countryName, $value ) ) {
                $hubin = $key;
                break;
            }
        }
        return $hubin;
    }
    protected function setData( $orderCode, $package ) {
        if( empty( $orderCode ) ) {
            $this->addError( '订单号为空' );
            return;
        }
        if( empty( $package ) ) {
            $this->addError( '包裹信息为空' );
            return;
        }
        $order = Service_Orders::getByField( $orderCode, 'order_code');
        $orderProducts = Service_OrderProduct::getByCondition( array( 'order_code' => $orderCode ) );
        $orderAddress = Service_OrderAddressBook::getByField( $orderCode, 'order_code' );
        if( empty( $orderProducts ) ) {
            $this->addError( '找不到订单产品' );
            return;
        }
        if( empty( $orderAddress ) ) {
            $this->addError( '找不到订单地址信息' );
            return;
        }

        $shipMethod = Service_ShippingMethod::getByField( $order['sm_code'], 'sm_code' );
        $weight = 0;
        $content = array();

        foreach( $package as $value ) {
            $volumeWeight = 0;
            if( $shipMethod['sm_vol_rate'] > 0 ) {
                $volume = $value['length'] * $value['width'] * $value['height'];
                $volumeWeight = round( $volume / $shipMethod['sm_vol_rate'], 3 );
            }
            $weight += $volumeWeight > $value['weight'] ? $volumeWeight : $value['weight'] ;
            $content[] = $value['op_description'];
        }

        $country = Service_Country::getByField( $orderAddress['oab_country_id'], 'country_id' );
        $invoice = array();
        $totalDeclaredValue = 0;

        $withBattery = false;
        $needInvoiceCountry = self::getNeedInvoiceCountry();

        foreach( $orderProducts as $value ) {
            $tmpPrice = sprintf( '%0.2f', $value['op_purpose_declared_value'] );
            $productTotalPrice = $value['op_quantity'] * $tmpPrice;
            $totalDeclaredValue += $productTotalPrice;
            //不支持无纸化的国家，就不要传invoice节点，哲盟那边是根据invoice节点来生成发票信息的
            if( !in_array( $orderAddress['oab_country_id'], $needInvoiceCountry ) ) {
                $invoice[] = array(
                    'EDescrNameE'       => $value['product_title_en'],
                    'Origin'             => 'CN',
                    'Qty'                => $value['op_quantity'],
                    'Price'              => $tmpPrice,
                    'TotalPrice'        => sprintf( '%0.2f', $productTotalPrice ),
                    'Cur'                => 'USD',
                );
            }
            //检查产品是否带点
            $product = Service_Product::getByField( $value['product_id'], 'product_id' );
            if( $product['with_battery'] == 1 ) {
                $withBattery = true;
            }
        }

        $address =  array( $orderAddress['oab_street_address1'], $orderAddress['oab_street_address2'] ? $orderAddress['oab_street_address2'] : '', '' );

        /* 重量使用三位小数点，例如1.222，没有数字也用0补齐，1KG则提交1.000；
         * 申报价值金额使用两位小数点，例如1.55，没有数字也用0补齐，1.5美金则提交1.50
         * 这样，一般最初对接客户最常反馈这个标准XML文件异常的都是这两个地方的问题，
         * 其余的地方则可参考说明文档
         */
        $xml = array(
            'Consignee' => array(
                'CompanyName'           => $orderAddress['oab_company'],
                'AddressLine'           => $address,
                'City'                   => $orderAddress['oab_city'],
                'PostalCode'            => $orderAddress['oab_postcode'],
                'CountryCode'           => $country['country_code'],
                'CountryName'           => $country['country_name_en'],
                'Contact'                => array(
                        'PersonName' => $orderAddress['oab_firstname'].( $orderAddress['oab_lastname'] ? ' '.$orderAddress['oab_lastname'] : '' ),
                        'PhoneNumber'=> $orderAddress['oab_cell_phone'] ? $orderAddress['oab_cell_phone'] : $orderAddress['oab_phone'],
                )
            ),
            'Dutiable' => array(
                'DeclaredValue' => sprintf( '%0.2f', $totalDeclaredValue ),
            ),
            'Reference'=> array(
                'ReferenceID' => $orderCode,
            ),
            'ShipmentDetails'=> array(
                'Date'=> date('Y-m-d'),
                'Contents'=> implode( ',', $content ),
                'Weight' => sprintf( '%0.3f', $weight ),
                'DescrType' => $withBattery ? 'PI967' : '',
            ),
        );
        if( $invoice ) {
            $xml['Invoice'] = $invoice;
        }

        $hubin = self::getHubIn( $country['country_code'] );
        if( empty( $hubin ) ) {
            $this->addError( '找不到对应的HubIn' );
            return;
        }
        $reqStr = Common_Common::arrayToXML( $xml );

        $this->_requestData = array(
            'type'                   => 1,
            'customerCode'          => 'JHE',
            'jobno'                  => $orderCode,
            'reqStr'                 => $reqStr,
            'clno'                   => $this->_clno,
            'hubIn'                  => $hubin,
            'authorizationNO'      => $this->_authorizationNO,
            'labelFormat'            => 'PDF'
        );
        //设置PDF文件名字
        $this->_pdfFileName = $orderCode.'.pdf';
        $this->_orderCode = $orderCode;
    }
    /* @todo；返回条用结果
     *
     */
    protected function getReturn() {
        $return = array( 'ask' => 0,'message'=>'');
        if( empty( $this->_error ) ) {
            $return['ask'] = 1;
            $return['PDF'] = $this->_pdfPath.DIRECTORY_SEPARATOR.$this->_pdfFileName;
            $return['AirwayBillNumber'] = $this->_trackingNumber; //跟踪号
            $return['LicensePlates'] = array();
            $return['message'] = 'success';
        } else {
            $return['message'] = implode( ',', $this->_error );
        }
        return $return;
    }
    /* @todo:获取PDF
     * @param string $orderCode 订单号
     * @param array  $package 包裹信息
     */
    public function createOrder( $orderCode, $package ) {

        if( !$this->_pdfPath ) {
            $this->addError( '请先设置PDF的保存路径' );
            return $this->getReturn();
        }
        $this->setData( $orderCode, $package );
        //print_r($this->_requestData);exit;
        if( $this->_error )
            return $this->getReturn();

        $result = $this->doRequest();

        if( $result === false )
            return $this->getReturn();

        if($result[0] == 'fail') {
            $this->addError( '获取PDF失败,'.$result[1] );

        } else {
            $this->_trackingNumber = $result[2];
            $orderPdfUrl = $result[3];

            //把PDF的地址保存起来，免得后面下载出错找不到地址
            $this->updateDhlApi( $result );

            //$mailPdfUrl = $result[4];
            //下载文件,这种就没必要当做错误了，因为已经返回success了
            if( false !== ( $orderPdfData = @file_get_contents( $orderPdfUrl ) ) ) {
                $file = $this->getPdfPath();
                if( false === file_put_contents( $file, $orderPdfData ) ) {
                    $this->addWarming( '保存PDF文件失败，下载地址:'.$orderPdfUrl );
                }
            } else {
                $this->addWarming( '下载打单PDF失败，下载地址:'.$orderPdfUrl );
            }
        }
        return $this->getReturn();
    }
    /* @todo:发送请求
     *
     */
    private function doRequest() {
        $httpClient = new Common_HttpClient( $this->_scheme.'://'.$this->_host,$this->_port );
        $httpClient->setDebug(true);
        $httpClient->setTimeOut(90);
        $file = APPLICATION_PATH.'/../data/log/DHL-TH_http_request.txt';
        $httpClient->setLogFile($file);
        $isSuccessful = $httpClient->post( $this->_service, $this->_requestData );
        if( !$isSuccessful ) {
            $this->addError( $httpClient->getError() );
            return false;
        }
        $content = $httpClient->getContent();
        //下面这条记录是哲盟真实的返回数据
        //$content = 'success;;null;;3380885023;;http://113.105.65.70:80/dhl_cust/downServlet?filePath=D:\TransformXMLtoPDF\PDFReports\JHE\SOEC00160829375.pdf;;http://113.105.65.70:80/dhl_cust/downServlet?filePath=D:\TransformXMLtoPDF\ChargedReports\JHE\SOEC00160829375.pdf';
        return $this->getResult( $content );;
    }
    /* @todo:获取返回结果
     *
     */
    private function getResult( $content ) {
        $result = false;
        if( $content === '' || is_null( $content ) ) {
            $this->addError( '誓盟接口返回的数据为空' );
            return $result;
        }
        //解释内容
        $data = explode( ';;', $content );
        if( $data[0] != 'success' && $data[0] != 'fail' ) {
            $this->addError( '誓盟接口返回的数据格式不正确，返回的数据:'.var_export( $content, true ) );
            return $result;
        } else if( $data[0] == 'success' ) {
            if( !isset( $data[2] ) || empty( $data[2] ) ) {
                $this->addError( '誓盟接口未返回转单号，返回的数据:'.var_export( $content, true ) );
                return $result;
            }
            if( !isset( $data[3] ) || empty( $data[3] ) ) {
                $this->addError( '誓盟接口未返回PDF下载地址，返回的数据:'.var_export( $content, true ) );
                return $result;
            }
        }
        return $data;
    }
    /* @todo:把返回的数据跟新进这个表
     * @param array $data 哲盟返回的数据
     */
    protected function updateDhlApi( $data ) {
        //先把地址保存下来
        $apiDhlRow = Service_ApiDhl::getByField( $this->_orderCode, 'order_code');
        if(empty($apiDhlRow)){
            $shipOrder = Service_ShipOrder::getByField( $this->_orderCode, 'order_code');
            $insertRow['order_code'] = $this->_orderCode;
            $insertRow['so_code'] = $shipOrder['so_code'];
            $insertRow['status'] = 2;
            $insertRow['create_time'] = date('Y-m-d H:i:s');
            $insertRow['airway_Bill_number'] = $data[2];
            $insertRow['comment'] = $data[3];
            Service_ApiDhl::add($insertRow);
        } else {
            $update = array(
                'airway_Bill_number'=>$data[2],
                'comment' => $data[3],
                'status' => 2,
            );
            Service_ApiDhl::update( $update, $apiDhlRow['ad_id'], 'ad_id');
        }
    }

}
