<?php

namespace App\Services\Ship;

use App\Events\CreateLogisticEvent;
use App\Models\GoodsSku;
use App\Models\ShopShip;
use App\Models\Waybill;
use App\Services\Business\KuaiTuanTuan\FaceSheet;

class WayBillService
{
    public $orders;
    public $objectId;
    // 快递便携式一联单
    public $sfOne = 'https://file-link.pinduoduo.com/sf_one';
    public $sfOneTemplate = 'sf_one1688973997895.xml';
    // 快递三联面单
    public $sfThree = 'https://file-link.pinduoduo.com/sf_three';
    public $sfThreeTemplate = 'sf_three1677381064344.xml';
    // 标准模板
    public $sfStd = 'https://file-link.pinduoduo.com/sf_std';
    public $sfStdTemplate = 'sf_std1677380804913.xml';
    // 时效类型
    public $timedDeliveryCode;

    public function getContents()
    {
        // 已下单过的订单不再下单
        $contents = [];
        foreach ($this->orders as $shopId => $order) {
            // 订单取消的情况暂不处理
            $shopShip = $this->getShopShip($shopId);
            $faceSheet = new FaceSheet();
            $faceSheet->setShop($shopShip);
            foreach ($order as $item) {
                [$sender, $orderInfo, $senderConfig] = $this->prepareRequest($item, $shopShip);
                $waybill = $this->saveWayBill($item, $shopShip, $senderConfig);

                if (empty($waybill->id)) {
                    $resp = $faceSheet->getWayBill($sender, $orderInfo, $senderConfig['wp_code']);
                    if (isset($resp['pdd_waybill_get_response'])) {
                        $data = $resp['pdd_waybill_get_response']['modules'][0];
                        $printData = json_decode($data['print_data'], true);
                        $waybill->request_id = $resp['pdd_waybill_get_response']['request_id'];
                        $waybill->encryptedData = $printData['encryptedData'];
                        $waybill->signature = $printData['signature'];
                        $waybill->templateUrl = $printData['templateUrl'];
                        $waybill->ver = $printData['ver'];
                        $waybill->waybill_code = $data['waybill_code'];
                        $waybill->save();
                        // 返回待打印内容
                        $contents[$waybill->id] = [
                            'addData' => [
                                'sender' => $sender,
                            ],
                            'encryptedData' => $printData['encryptedData'],
                            'signature' => $printData['signature'],
                            'templateUrl' => env('APP_URL') . '/ktt/' . $this->sfOneTemplate, // 电子面单模板
                            'ver' => $printData['ver'],
                            'userid' => $waybill->user_id,
                            'items' => $item['items'],
                            'documentID' => $waybill->id,
                            'order_id' => $item['id'],
                            'participate_no' => $waybill->participate_no,
                            'note' => $waybill->note,
                        ];
                        event(new CreateLogisticEvent($shopShip->shop_id, $waybill->order_sn, $data['waybill_code']));
                    }
                } else {
                    $contents[$waybill->id] = [
                        'addData' => [
                            'sender' => $sender,
                        ],
                        'encryptedData' => $waybill->encryptedData,
                        'signature' => $waybill->signature,
                        'templateUrl' => env('APP_URL') . '/ktt/' . $this->sfOneTemplate, // 电子面单模板
                        'ver' => $waybill->ver,
                        'userid' => $waybill->user_id,
                        'items' => json_decode($waybill->items, true),
                        'documentID' => $waybill->id,
                        'order_id' => $item['id'],
                        'participate_no' => $waybill->participate_no,
                        'note' => $waybill->note,
                    ];
                }
            }
        }

        return $contents;
    }

    public function getDocumentsAndOrderIds($contents)
    {
        // 打印单,根据商品排序
        $items = [];
        foreach ($contents as $docId => $content) {
            foreach ($content['items'] as $item) {
                if ($item['is_single']) {
                    $items[$item['external_sku_id']][] = $docId;
                }
            }
        }
        ksort($items);
        $documents = $orderIds = $hasIds = [];
        foreach ($items as $docIds) {
            $docIds = array_unique($docIds);
            $docIds = array_diff($docIds, $hasIds);
            $hasIds = array_merge($hasIds, $docIds);
            foreach ($docIds as $docId) {
                $orderIds[] = $contents[$docId]['order_id'];
                $documents[] = $contents[$docId];
            }
        }

        return [$documents, $orderIds];
    }

    private function saveWayBill($order, $shopShip, $senderConfig)
    {
        $waybill = Waybill::query()->firstOrNew(
            ['order_sn' => $order['order_sn']]
        );

        $waybill->shop_id = $shopShip->shop_id;
        $waybill->object_id = $this->objectId;

        $waybill->sender_country = $senderConfig['country'];
        $waybill->sender_province = $senderConfig['province'];
        $waybill->sender_city = $senderConfig['city'];
        $waybill->sender_district = $senderConfig['district'];
        $waybill->sender_detail = $senderConfig['detail'];
        $waybill->sender_name = $senderConfig['name'];
        $waybill->sender_mobile = $senderConfig['mobile'];

        $waybill->recipient_province = $order['recipient_province'];
        $waybill->recipient_city = $order['recipient_city'];
        $waybill->recipient_district = $order['recipient_district'];
        $waybill->recipient_detail = $order['recipient_detail'];
        $waybill->recipient_name = $order['recipient_name'];
        $waybill->recipient_mobile = $order['recipient_mobile'];

        $waybill->user_id = $shopShip->owner_id;
        $waybill->wp_code = $senderConfig['wp_code'];
        $waybill->order_sn = $order['order_sn'];
        $waybill->order_id = $order['id'];
        $waybill->participate_no = $order['participate_no'];
        $waybill->note = $order['note'];
        $waybill->items = json_encode($order['items'], 256);

        return $waybill;
    }

    private function getTimedDelivery($order)
    {
        $this->timedDeliveryCode = Waybill::$BUSINESS_EXPRESS_CODE;
        $address = [
            '辽宁省' => [],
            '吉林省' => [],
            '黑龙江省' => [],
            '甘肃省' => [],
            '海南省' => [],
            '宁夏回族自治区' => [
                '银川市', '石嘴山市', '吴忠市', '固原市'
            ],
            '青海省' => [
                '西宁市', '海东市', '海北藏族自治州', '黄南藏族自治州', '海南藏族自治州', '玉树藏族自治州'
            ],
        ];
        if (isset($address[$order['recipient_province']])) {
            if (empty($address[$order['recipient_province']])) {
                $this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
            }
            if ($address[$order['recipient_province']] && in_array($order['recipient_city'], $address[$order['recipient_province']], true)) {
                $this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
            }
        }
    }

    private function prepareRequest($order, $shopShip)
    {
        $this->getTimedDelivery($order);

        $this->setObjectId();

        $items = [];
        foreach ($order['items'] as $item) {
            if ($item['should_print']) {
                // 使用规格编码后删除,此处暂时使用空运名字判断兼容
                if (false !== strpos($item['name'], '空运')) {
                    $this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
                }

                $items[] = [
                    'name' => $item['name'],
                    'count' => $item['count'],
                ];
            }
        }

        $senderConfig = [];
        foreach ($shopShip->senders as $sender) {
            if ($sender['timed_delivery_code'] === $this->timedDeliveryCode) {
                $senderConfig = $sender;
                break;
            }
        }

        if (empty($senderConfig)) {
            abort(404, '发货人信息未匹配');
        }
        $sender = [
            'address' => [
                'city' => $senderConfig['city'],
                'country' => $senderConfig['country'],
                'detail' => $senderConfig['detail'],
                'district' => $senderConfig['district'],
                'province' => $senderConfig['province'],
            ],
            'name' => $senderConfig['name'],
            'mobile' => $senderConfig['mobile'],
        ];

        $orderInfo = [
            'logistics_services' => [
                'TIMED-DELIVERY' => [
                    'value' => $this->timedDeliveryCode
                ],
            ],
            'object_id' => $this->objectId,
            'order_info' => [
                'order_channels_type' => 'PDD',
                'trade_order_list' => [$order['order_sn']],
            ],
            'package_info' => [
                'items' => $items,
            ],
            'recipient' => [
                'address' => [
                    'city' => $order['recipient_city'],
                    'detail' => $order['recipient_detail'],
                    'district' => $order['recipient_district'],
                    'province' => $order['recipient_province'],
                ],
                'name' => $order['recipient_name'],
                'mobile' => $order['recipient_mobile'],
            ],
            'template_url' => $this->sfOne,
            'user_id' => $shopShip->owner_id,
        ];

        return [$sender, $orderInfo, $senderConfig];
    }

    public function setObjectId()
    {
        $this->objectId = date('YmdHis') . str_pad(mt_rand(1, 9999999), 7, '0', STR_PAD_LEFT);

        return $this;
    }

    public function setOrders($orders)
    {
        $orders = $orders->toArray();
        // 取出所有组合商品编码
        $combinationExternalIds = [];
        foreach ($orders as $order) {
            foreach ($order['items'] as $item) {
                if (false !== strpos($item['external_sku_id'], 'Z')) {
                    $combinationExternalIds[] = $item['external_sku_id'];
                }
            }
        }
        // 获取组合商品详情
        $combinations = [];
        if ($combinationExternalIds) {
            $goodsSkus = GoodsSku::query()
                ->select(['id', 'external_sku_id'])
                ->with([
                    'combinationGoods:id,goods_sku_id,item_id,item_num',
                    'combinationGoods.goodsSkuItem:id,external_sku_id',
                ])
                ->whereIn('external_sku_id', $combinationExternalIds)
                ->get()
                ->toArray();
            foreach ($goodsSkus as $goodsSku) {
                foreach ($goodsSku['combination_goods'] as $item) {
                    $combinations[$goodsSku['external_sku_id']][] = [
                        'count' => $item['item_num'],
                        'external_sku_id' => $item['goods_sku_item']['external_sku_id'],
                    ];
                }
            }
        }
        // 订单拆分组合
        foreach ($orders as $order) {
            $info = [
                'id' => $order['id'],
                'order_sn' => $order['order_sn'],
                'recipient_province' => $order['receiver_address_province'],
                'recipient_city' => $order['receiver_address_city'],
                'recipient_district' => $order['receiver_address_district'],
                'recipient_detail' => $order['receiver_address_detail'],
                'recipient_name' => $order['receiver_name'],
                'recipient_mobile' => $order['receiver_mobile'],
                'participate_no' => $order['is_supplier'] ? $order['participate_no'] : $order['supply_participate_no'],
                'note' => $order['business_note'] ? $order['business_note'] . ',' . $order['buyer_memo'] : $order['buyer_memo'],
                'items' => []
            ];
            foreach ($order['items'] as $item) {
                $count = $item['goods_number'] - $item['already_cancel_number'];
                if (isset($combinations[$item['external_sku_id']])) {
                    $info['items'][] = [
                        'is_single' => false,
                        'should_print' => true,
                        'name' => $item['goods_name'],
                        'count' => $count,
                        'external_sku_id' => $item['external_sku_id'],
                    ];
                    foreach ($combinations[$item['external_sku_id']] as $combinationItem) {
                        $info['items'][] = [
                            'is_single' => true,
                            'should_print' => false,
                            'count' => $count * $combinationItem['count'],
                            'external_sku_id' => $combinationItem['external_sku_id'],
                        ];
                    }
                } else {
                    $info['items'][] = [
                        'is_single' => true,
                        'should_print' => true,
                        'name' => $item['goods_name'],
                        'count' => $count,
                        'external_sku_id' => $item['external_sku_id'],
                    ];
                }
            }
            $this->orders[$order['shop_id']][] = $info;
        }

        return $this;
    }

    private function getShopShip($shopId)
    {
        return ShopShip::query()
            ->select(['id', 'shop_id', 'access_token', 'owner_id'])
            ->where('shop_id', $shopId)
            ->with([
                'senders' => function ($query) {
                    $query->where('status', 1)->orderBy('sort');
                }
            ])
            ->first();
    }
}
