<?php

namespace App\Services\WayBill\JingDong;

use App\Enum\Pickup\ConsignType;
use App\Models\BusinessOrder;
use App\Models\OrderItem;
use App\Models\Pickup;
use App\Models\Waybill;
use App\Services\Pickup\Exceptions\KdNiaoException;
use App\Utils\Env\EnvUtils;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;
use Lop\LopOpensdkPhp\Filters\ErrorResponseFilter;
use Lop\LopOpensdkPhp\Filters\IsvFilter;
use Lop\LopOpensdkPhp\Options;
use Lop\LopOpensdkPhp\Support\DefaultClient;
use Lop\LopOpensdkPhp\Support\GenericRequest;
use Psr\Http\Message\ResponseInterface;

class JingDongService
{
    public $baseUrl;
    public $appKey;
    public $appSecret;
    public $accessToken;
    public $customerCode;
    public static $CANCEL_TYPE = [
        1 => '预约信息有误',
        2 => '快递员无法取件',
        3 => '上门太慢',
        4 => '运费太贵',
        7 => '联系不上快递员',
        8 => '快递员要求取消',
        11 => '其他（如疫情管控，无法寄 件）',
        9 => '预约信息有误',
    ];

    public function __construct()
    {
        $this->baseUrl = "https://api.jdl.com";
        $this->appKey = "5ee218f6619e438db8755ee560c3eaa7";
        $this->appSecret = "7ffb176f75014ebbb37061f051024bf3";
        $this->accessToken = "4e411a1d178147cdb58b5579a0df378d";//每年都会过期 https://oauth.jdl.com/oauth/authorize?client_id=YOUR_APP_KEY&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code
        //生产环境域名：https://oauth.jdl.com 预发环境域名：https://uat-oauth.jdl.com
        $this->domain = "FreshMedicineDelivery";//对接方案的编码 生鲜快递
        $this->customerCode = "028K4188368";//月结编码
        /*if (!EnvUtils::checkIsProduce()) {
            //沙箱环境
            $this->baseUrl = "https://test-api.jdl.com";
            $this->appKey = "62d07644754843cc882fca7c01476c4f";
            $this->appSecret = "0c2c8b6b7c10481ea639f6daa09ac02e";
            $this->accessToken = "78c246c0ab564e67add6296a9eaf04a1";;//每年都会过期 https://oauth.jdl.com/oauth/authorize?client_id=YOUR_APP_KEY&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code
            $this->customerCode = "27K1234912";//月结编码
        }*/

    }

    public function request($body, $path)
    {
        // 生产环境: https://api.jdl.com
        $client = new DefaultClient($this->baseUrl);
        // 系统参数，应用的app_ley和app_secret，可从【控制台-应用管理-概览】中查看；access_token是用户授权时获取的令牌，用户授权相关说明请查看https://cloud.jdl.com/#/devSupport/53392
        $isvFilter = new IsvFilter($this->appKey, $this->appSecret, $this->accessToken);
        $errorResponseFilter = new ErrorResponseFilter();

        $request = new GenericRequest();
        $request->setDomain($this->domain);//对接方案的编码，应用订购对接方案后可在订阅记录查看
        $request->setPath($path);//api的path，可在API文档查看
        $request->setMethod("POST");//只支持POST
        // 序列化后的JSON字符串
        $request->setBody(json_encode([$body]));

        // 为请求添加ISV模式过滤器，自动根据算法计算开放平台鉴权及签名信息
        $request->addFilter($isvFilter);
        // 为请求添加错误响应解析过滤器，如果不添加需要手动解析错误响应
        $request->addFilter($errorResponseFilter);

        $options = new Options();

        $options->setAlgorithm(Options::MD5_SALT);
        Log::info("京东请求body:{$path}", [$body]);
        $response = $client->execute($request, $options);
        $response = json_decode($response->getBody(), true);
        Log::info("京东返回请求response", [$response]);
        if (!isset($response['code']) || ($response['code'] != 0 && $response['code'] != 1 && $response['code'] != 1000)) {
            throw new \Exception($response['message'] ?? "code异常");
        }
        return $response;
    }


    private function buildCargoes($extend)
    {
        return [
            "quantity" => $extend["quantity"] ?? 1,
            "goodsName" => "鲜花",
            "volume" => ($extend['volume'] ?? 0) > 0 ? $extend['volume'] : 100,
            "weight" => $extend['weight'] ?? 1,
            "packageQty" => 1
        ];
    }

    public function buildContact($params)
    {
        return [
            'senderName' => $params['name'] ?? '',
            'senderPhone' => $params['mobile'] ?? '',
            'senderAddress' => substr($params['province_name'] . $params['city_name'] . $params['area_name'] . $params['address_detail'], 0, 350),
        ];
    }

    public function createOrder(Waybill $pickup)
    {
        $path = "/freshmedicinedelivery/delivery/create/order/v1";
        $pickupData = $pickup->toArray();
        $body = [
            "orderId" => $pickupData['order_sn'],
            "senderContactRequest" => [
                'senderName' => $pickupData['sender_name'] ?? '',
                'senderPhone' => $pickupData['sender_mobile'] ?? '',
                'senderAddress' => substr($pickupData['sender_province'] . $pickupData['sender_city']
                    . $pickupData['sender_district'] . $pickupData['sender_detail'], 0, 350)
            ],
            "customerCode" => $this->customerCode,
            "remark" => $pickup['note'] ?? '',
            "salePlatform" => '0030001',//其他平台
            "cargoesRequest" => $this->buildCargoes($pickup),
            "receiverContactRequest" => [
                'receiverName' => $pickupData['recipient_name'] ?? '',
                'receiverPhone' => $pickupData['recipient_mobile'] ?? '',
                'receiverAddress' => substr($pickupData['recipient_province'] . $pickupData['recipient_city'] . $pickupData['recipient_district'] . $pickupData['recipient_detail'], 0, 350)
            ],
            "channelOrderId" => $pickupData['order_sn'],
            "promiseTimeType" => 26,//22：医药冷链 26：冷链专送,29医药专送
            "goodsType" => 7,//1:普通，2:生鲜常温，5:鲜活，6:控温，7:冷藏，8:冷冻，9:深冷；21:医药冷藏，23:医药控温，24:医药常温，25:医药冷冻，27:医药深冷
            //"pickUpStartTime" => Carbon::today()->startOfDay()->addDays(2)->addHours(19)->toDateTimeString(),
            //"pickUpEndTime" => Carbon::today()->startOfDay()->addDays(2)->addHours(21)->toDateTimeString(),
        ];

        $response = $this->request($body, $path);
        return $response['data'];

    }


    public function cancelOrder(Waybill $pickup)
    {
        $path = "/freshmedicinedelivery/delivery/cancel/waybill/v1";
        $pickupData = $pickup->toArray();
        $body = [
            "waybillNo" => $pickupData['waybill_code'],
            "customerCode" => $this->customerCode,
            "interceptReason" => "订单信息有误",
        ];
        $response = $this->request($body, $path);

        return $response['data'];
    }

    public function pullData(Waybill $pickup)
    {
        //云打印
        $this->domain = "jdcloudprint";
        $path = "/PullDataService/pullData";
        $pickupData = $pickup->toArray();
        $body = [
            "cpCode" => "JD",
            "wayBillInfos" => [[
                'orderNo' => $pickupData['order_sn'],
                'jdWayBillCode' => $pickupData['waybill_code'],
            ]],
            "parameters" => ["ewCustomerCode" => $this->customerCode],
            "objectId" => $pickupData['object_id'],
        ];
        $response = $this->request($body, $path);

        return $response['prePrintDatas'];
    }


    public function queryOrder(Waybill $pickup)
    {
        $path = "/ecap/v1/orders/details/query";
        $pickupData = $pickup->toArray();
        $body = [
            "waybillCode" => $pickupData['ship_sn'] ?? '',
            "orderCode" => $pickupData['out_order_sn'] ?? "",
            "customerCode" => $this->customerCode,
            "orderOrigin" => 2,
        ];
        $response = $this->request($body, $path);

        return $response['data'];
    }

    public function subscribe(Waybill $pickup)
    {
        $path = "/jd/tracking/subscribe";
        $pickupData = $pickup->toArray();
        $body = [
            "referenceNumber" => $pickupData['ship_sn'] ?? '',
            "referenceType" => 20000,
            "customerCode" => $this->customerCode,
        ];
        $this->domain = "Tracking_JD";//对接方案的编码
        $response = $this->request($body, $path);

        return $response['data'];
    }

    public function queryFee(Waybill $pickup)
    {
        $path = "/ecap/v1/orders/actualfee/query";
        $pickupData = $pickup->toArray();
        $body = [
            "waybillCode" => $pickupData['ship_sn'] ?? '',
            "orderCode" => $pickupData['out_order_sn'] ?? "",
            "customerCode" => $this->customerCode,
            "orderOrigin" => 2,
        ];
        $response = $this->request($body, $path);

        return $response['data'];
    }

    public function queryTrace(Waybill $pickup)
    {
        $path = "/freshmedicinedelivery/delivery/query/waybill/gis/v1";
        $pickupData = $pickup->toArray();
        $body = [
            "waybillNo" => $pickupData['waybill_code'] ?? '',
            "customerCode" => $this->customerCode,
        ];
        $response = $this->request($body, $path);

        return $response['data'];
    }


}

