<?php

namespace common\helpers;

use common\models\OrderGoods;
use common\models\Region;
use common\models\ShopGoods;
use Yii;

class Logistics
{
    const prodDomain = 'https//warehouse.taoplus.com.my';
    const testDomain = 'http://warehouse.worldsyntech.com';

    // 1.获取bearer token,此token是其他api调用时的必传参数.
    const authenticationUrl = 'http://warehouse.taoplus.com.my/index.php?route=rest/admin_security/api_login&grant_type=client_credentials';
    // 2.创建订单和产品(以前不存在/已提交的产品).
    const createOrderUrl = 'http://warehouse.taoplus.com.my/index.php?route=rest/warehouse_api/add_order';
    // 3.获取产品/包裹的重量和状态.
    const getProductUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/get_order_product';
    // 4.获取订单重量，m3，包装的包裹数量，费用跟踪号码和状态.
    const getOrderUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/get_order';
    // 5.通知仓库已经付款，包裹可以投递.
    const notifyDeliveryUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/ warehouse_api/notify_delivery';
    // 6.创建产品/包裹.
    const addProductUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/add_order_product';
    // 7.创建交付订单并将现有产品绑定到订单.需要先调用接口6创建商品.
    const createOrderSimpleUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/add_order_simple';
    // 8.计算订单费用,并将订单状态改为待付款.
    const stockOutUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/stock_out';
    // 9.通知物流系统订单不可删除.error包含错误的订单ID.
    const notifyOrderUndeletableUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/notify_order_undeletable';
    // 10.取消订单产品/包裹。它将状态更改为无效，并保留订单产品/包裹.
    const cancelOrderProductUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/cancel_order_product';
    // 11.从数据库中删除订购产品/包裹.
    const deleteOrderProductUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/delete_order_product';
    // 12.取消订单,状态改为无效,保留订单不删除.
    const cancelOrderUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/cancel_order';
    // 13.从数据库中删除订单.
    const deleteOrderUrl = 'http://warehouse.worldsyntech.com/index.php?route=rest/warehouse_api/delete_order';
    // 14.运单追踪.
    const trackOrderUrl = 'https://taoplus.com.my/index.php?route=information/order_tracking/json&order_tracking_search=';

    // accessToken的缓存key
    const wstLogisticsBearerTokenKey = 'wstLogisticsBearerToken';

    // 国家
    const country = 'China';

    function __construct()
    {
//         if (!\Yii::$app->redis->get(self::wstLogisticsBearerTokenKey)) {
            $this->getAuthentication();
//         }
    }

    /**
     * 通用curl接口.
     * @param string $url api接口url
     * @param array $request_body 参数
     * @return mixed
     */
    function curl($url, $request_body)
    {
        $accessToken = \Yii::$app->redis->get(self::wstLogisticsBearerTokenKey);

        $ch = curl_init($url);
        header('Content-Type: application/json');
        $authorization = "Authorization: Bearer " . $accessToken;
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', $authorization]);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request_body));
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }

    // 1.获取bearer token,此token是其他api调用时的必传参数.
    function getAuthentication()
    {
        $request = [
            'user_name' => Yii::$app->params['wst']['userName'],
            'password' => Yii::$app->params['wst']['password'],
            'agent_id' => Yii::$app->params['wst']['agentId'],
        ];

        $ch = curl_init(self::authenticationUrl);
        header('Content-Type: application/json');
        $authorization = "Authorization: Basic " . Yii::$app->params['wst']['baseToken'];
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', $authorization]);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request));
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        $response = curl_exec($ch);

        curl_close($ch);

        $result = json_decode($response, true);
        if ($result['success']) {
            // token和过期时间写入redis
            \Yii::$app->redis->set(self::wstLogisticsBearerTokenKey, $result['data']['access_token']);
            \Yii::$app->redis->expire(self::wstLogisticsBearerTokenKey, $result['data']['expires_in']);
        }
    }

    // 2.创建订单和产品(以前不存在/已提交的产品).
    function createOrder($order)
    {
        $request = [
            'order_no' => $order['SN'],   // 客户系统中的订单号
            'delivery_method_id' => '60', // 快递方式ID. TODO: 133(test)
            'warehouse_id' => '1',   // 仓库ID. TODO:
            'country' => 'China',    // 收件人国家 Malaysia
            'state' => Region::getCnName($order['PROVINCE']), // ,   // 收件人省 Johor(test)
            'city' => Region::getCnName($order['CITY']) . Region::getCnName($order['COUNTY']),   // 收件市县
            'post_code' => $order['ZIP_CODE'], // 收件人邮政编码
            'address' => $order['ADDRESS'],    // 收件人送货地址
            'consignee' => $order['CONSIGNEE_REAL_NAME'],  // 收货人姓名，使用订单中的收货人真实姓名
            'consignee_ic_number' => $order['CONSIGNEE_ID_NO'], // 收件人身份证号
            'telephone' => $order['MOBILE'],  // 收件人电话号码
            'sender' => 'Elken',    // 发件人名字
            'sender_country' => 'Malaysia',    // 发件人国家
            'sender_state' => 'Selangor', // ,   // 发件人省
            'sender_city' => 'Kuala Lumpur',   // 发件人市县
            'sender_post_code' => '47620', // 发件人邮政编码
            'sender_address' => '11, 2nd Floor, Jalan TP5, Taman Perindustrian UEP, Subang Jaya',    // 发件人地址
            'sender_telephone' => '0380210088',  // 发件人电话号码
            'volumetric_details' => '3*4*20',    // 规格
        ];

        // 查询商品
        $orderGoods = OrderGoods::find()
            ->alias('O')
            ->join('INNER JOIN', ShopGoods::tableName() . ' AS G', 'G.ID=O.GOODS_ID')
            ->where('O.ORDER_SN=:ORDER_SN', [':ORDER_SN' => $order['SN']])->select('O.ORDER_SN,O.REAL_PRICE,O.BUY_NUMS,O.SKU_CODE,O.GOODS_TITLE,G.CONTENT')
            ->asArray()
            ->all();
        // 需要数量乘倍数的产品编号
        $stackedProducts = Cache::getSystemConfig()['stackedProducts']['VALUE'];
        $stackedProducts = explode(',', $stackedProducts);

        $products = [];
        foreach ($orderGoods as $item) {
            $products[] = [
                'product_no' => $item['SKU_CODE'], // 客户系统中的产品编号
                'product_name' => $item['GOODS_TITLE'],   // 产品名称
                'tracking_number' => Date::today('Ymd') . $this->_random(10, 1),
                'quantity' => in_array($item['SKU_CODE'], $stackedProducts) ? $item['BUY_NUMS'] * 2 : $item['BUY_NUMS'],       // 产品数量
                'total_price' => number_format(100, 2, '.', ''),    // 订单总金额,Decimal 方便通关,固定100马币
                'currency_code' => 'MYR',  // 产品的货币代码. 如USD(美元),MYR(马来西亚林吉特),SGD(新加坡元),CNY(人民币)
                'supplier' => 'MRT',    // 品牌
                'remark' => $item['CONTENT'], // 备注:规格
            ];
        }
        $request['products'] = $products;

        LoggerTool::debug($request);

        return $this->curl(self::createOrderUrl, $request);
    }

    // 3.获取产品/包裹的重量和状态.
    function getProduct($order)
    {
        $request = [
            'tracking_number' => '027300027300',
        ];

        $response = $this->curl(self::getProductUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 4.获取订单重量，m3，包装的包裹数量，费用跟踪号码和状态
    function getOrder($order)
    {
        $request = [
            'order_id' => 'elg8-785',
        ];

        $response = $this->curl(self::getOrderUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 5.通知仓库已经付款，包裹可以投递.
    function notifyDelivery($order)
    {
        $request = [
            'order_id' => 'elg8-785',
        ];

        $response = $this->curl(self::notifyDeliveryUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 6.创建产品/包裹.
    function addProduct($orderProducts)
    {
        $products = [];
        foreach ($orderProducts as $item) {
            $products[] = [
                "product_no" => $item['SKU_CODE'],
                "product_name" => $item['GOODS_TITLE'],
                "tracking_number" => '',
                "quantity" => $item['BUY_NUMS'],
                "total_price" => $item['REAL_PV'],
                "currency_code" => "CNY",
            ];
        }

        $request = [
            'warehouse_id' => '1',
            "products" => $products
        ];

        $response = $this->curl(self::addProductUrl, $request);
        LoggerTool::info($response);
        return $response;
    }

    // 7.创建交付订单并将现有产品绑定到订单.需要先调用接口6创建商品.
    function createOrderSimple($order)
    {
        $request = [
            "order_no" => "T-1000",
            "delivery_method_id" => "39",
            "warehouse_id" => "1",
            "country" => "Malaysia",
            "state" => "Pulau Pinang",
            "city" => "Bukit Mertajam",
            "post_code" => "14000",
            "address" => "1584,JALAN NANGKA,TAMAN JAMBU MAWAR,14000 BUKIT MERTAJAM",
            "consignee" => "TSA",
            "consignee_ic_number" => "111111-11-1111",
            "telephone" => "017-5423223",
            "cod" => "CNY",
            "cod_currency_code" => "100",
            "address_area" => "",
            "address_subdivision" => "",
            "products" => [
                [
                    "product_no" => "12345",
                    "tracking_number" => "2019061112A1",
                ],
                [
                    "product_no" => "23456",
                    "tracking_number" => "20190604_A12",
                ]
            ]
        ];

        $response = $this->curl(self::createOrderSimpleUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 8.根据货物重量计算订单费用,并更改订单状态为待付款
    function stockOut($order)
    {
        $request = [
            'order_id' => 'elg8-785',
            'weight' => '2.5', // 订单重量(KG)
        ];

        $response = $this->curl(self::stockOutUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 9.通知物流系统订单不可删除. error包含错误的订单ID.
    function notifyOrderUndeletable($order)
    {
        $request = [
            'order_ids' => ['elg8-785']
        ];

        $response = $this->curl(self::notifyOrderUndeletableUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 10.取消订单产品/包裹。它将状态更改为无效，并保留订单产品/包裹.
    function cancelOrderProduct($order)
    {
        $request = [
            'order_product_ids' => ['15895', '15896', '15897']
        ];

        $response = $this->curl(self::cancelOrderProductUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 11.从数据库中删除订购产品/包裹.
    function deleteOrderProduct($order)
    {
        $request = [
            'order_product_ids' => ['15895', '15896', '15897']
        ];

        $response = $this->curl(self::deleteOrderProductUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 12.取消订单,状态改为无效,保留订单不删除.
    function cancelOrder($order)
    {
        $request = [
            'order_ids' => ['elg8-787', 'elg8-786']
        ];

        $response = $this->curl(self::cancelOrderUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 13.从数据库中删除订单.
    function deleteOrder($order)
    {
        $request = [
            'order_ids' => ['elg8-787', 'elg8-786']
        ];

        $response = $this->curl(self::deleteOrderUrl, $request);
        LoggerTool::info($response);

        return $response;
    }

    // 13.从数据库中删除订单.
    function trackOrder($trackNo)
    {
        // 运单号
        $trackNo = 'TBS10182495KJ2430';

        $curl = curl_init();
        curl_setopt($curl,CURLOPT_TIMEOUT,5000);
        curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,false);
        curl_setopt($curl,CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
        curl_setopt($curl,CURLOPT_URL, self::trackOrderUrl . $trackNo);
        curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
        $response = curl_exec($curl);
        if (!$response) {
            $error = curl_errno($curl);
            curl_close($curl);
            LoggerTool::error($error);
            return false;
        }
        curl_close($curl);

        $result = json_decode($response, true);
        LoggerTool::info($result);

        return $result['data'];
    }

    /**
     * 生成随机数
     * @param $length
     * @param int $numeric
     * @return string
     */
    private function _random($length, $numeric = 0) {
        $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
        $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
        $hash = '';
        $max = strlen($seed) - 1;
        for ($i = 0; $i < $length; $i++) {
            $hash .= $seed[mt_rand(0, $max)];
        }
        return $hash;
    }
}