<?php

namespace App\Services\Business;

use App\Events\BusinessOrderCancelEvent;
use App\Events\BusinessOrdersUpdate;
use App\Models\BusinessGoodsSku;
use App\Models\BusinessOrder;
use App\Models\BusinessOrderItem;
use App\Models\BusinessOrderServer;
use App\Models\GoodsSku;
use App\Models\Log;
use App\Models\Shop;
use App\Pool\Core\Redis;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Auth;
use GuzzleHttp\Promise;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log as LogFile;

abstract class BusinessClient
{
    protected $redirectUri = 'http://erp.chutang66.com/callback';
    protected $code;
    protected $shop;
    protected $skuId = 0;

    abstract public function auth();

    abstract public function downloadGoodsListAndBind($activityNo);

    abstract public function downloadGoods($skuId);

    abstract public function bindGoods($goods);

    abstract public function createLogistic($orderSn, $waybillNo);

    abstract public function cancelLogistic($orderSn, $waybillNo);

    abstract public function incrQuantity($businessGoodsSku, $num, $incremental);

    abstract public function downloadOrdersAndSave($beginTime, $endTime, $downloadType = 'default', $page = 1);
    abstract public function downloadOrdersAndSaveServer($beginTime, $endTime, $page = 1);

    public function saveOrders($orders)
    {
        $shopId = $this->getShop()->id;
        foreach ($orders as $order) {
            unset($order['custom_item_list'], $order['logistics_list'], $order['gift_order_list'], $order['updated_at']);
            $order['shop_id'] = $shopId;
            $orderRecord = BusinessOrder::firstOrNew(['shop_id' => $shopId, 'order_sn' => $order['order_sn']], $order);
            if (empty($orderRecord->id)) {
                $orderRecord->save();
            } else {
                $orderRecord->update($order);
            }
            if (!empty($order['cancel_status'])) {
                event(new BusinessOrderCancelEvent($shopId, $order['order_sn']));
            }
            $goodsSkuNum = 0;
            foreach ($order['sub_order_list'] as $item) {
                $item['shop_id'] = $shopId;
                $orderItem = BusinessOrderItem::firstOrNew(['shop_id' => $shopId, 'business_order_id' => $orderRecord->id, 'goods_id' => $item['goods_id'], 'sku_id' => $item['sku_id']], $item);
                if ($item['external_sku_id']) {
                    $goodsSku = GoodsSku::query()
                        ->with('combinationGoods')
                        ->where('external_sku_id', $item['external_sku_id'])
                        ->first('external_sku_id');
                    $combinationNum = $goodsSku ? ($goodsSku->combinationGoods->count() ?: 1) : 1;
                    $goodsSkuNum += $combinationNum;
                } else {
                    $goodsSkuNum++;
                }
                $num = 0;
                $cancelNum = $item['already_cancel_number'] ?? 0;
                if (empty($orderItem->id)) {
                    if ((int)$item['cancel_status']) {
                        if ($num = $item['goods_number'] - $cancelNum) {
                            // 扣库存 $reduceNum
                            $num = 0 - $num;
                        }
                    } else {
                        // 扣库存
                        $num = 0 - $item['goods_number'];
                    }
                    $orderItem->save();
                } else {
                    if ($item['cancel_status'] != $orderItem->cancel_status) {
                        if ((int)$item['cancel_status']) {
                            // 加库存
                            $num = $cancelNum;
                        } else {
                            // 扣库存
                            $num = 0 - $item['goods_number'];
                        }
                    }
                    $orderItem->update($item);
                }
                // 增量更新库存
                if ($num && $item['external_sku_id']) {
                    event(new BusinessOrdersUpdate($orderItem, $num));
                }
            }
            $orderRecord->goods_sku_num = $goodsSkuNum;
            $orderRecord->save();
        }
    }
    public function saveOrdersServer($orders)
    {
        $shopId = $this->getShop()->id;
        $model=new BusinessOrderServer();
        $redis=new Redis();
        foreach ($orders as $k=>$v){
            $key='orderReturn::'.$v['order_sn'];
            if (!$redis->exists($key)){
                $redis->set($key,md5(json_encode($v)));
                $model->shop_id=$shopId;
//                $model->refund_amount=number_format($v['apply_extension']['refund_amount']/100,2);
                $model->refund_amount=$v['apply_extension']['refund_amount'];
                $model->refund_shipping_amount=$v['apply_extension']['refund_shipping_amount'];
                $model->description=$v['apply_extension']['description'];
                $model->reason=$v['apply_extension']['reason'];
                $model->sub_extensions=isset($v['apply_extension']['sub_extensions'])?json_encode($v['apply_extension']['sub_extensions']):'';
                $model->order_sn=$v['order_sn'];
                $model->after_sales_status=$v['after_sales_status'];
                $model->apply_type=$v['apply_type'];
                $model->created_at=$v['created_at'];
                $model->updated_at=$v['updated_at'];
                $model->save();
                if (isset($v['apply_extension']['sub_extensions'])){
                    $arr=$v['apply_extension']['sub_extensions'];
                    foreach ($arr as $k1=>$v1){
                        $v1[$k1]['shop_id']=$shopId;
                        $v1[$k1]['order_sn']=$v['order_sn'];
                        $v1[$k1]['business_order_server_id']=$model->id;
                    }
                    DB::table('business_order_server_item')->insert($arr);
                }
            }

        }
    }

    public function authCallback($code, $shop)
    {
        $this->setCode($code);
        $this->setShop($shop);
        $this->auth();

        return $this;
    }

    public function setShopWithId($shopId)
    {
        $this->shop = Shop::query()->find($shopId);

        return $this;
    }

    public function setShop($shop)
    {
        $this->shop = $shop;

        return $this;
    }

    public function getShop()
    {
        return $this->shop;
    }

    public function setCode($code)
    {
        $this->code = $code;

        return $this;
    }

    public function getCode()
    {
        return $this->code;
    }

    public function formDataPostRequest($url, $params)
    {
        $method = 'POST';
        $headers = [
            'headers' => ['Content-type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
            'form_params' => $params
        ];
        $res = (new Client())->request($method, $url, $headers);
        $size = $res->getBody()->getSize();
        $res = json_decode($res->getBody()->getContents(), true);
        $paramsJson = json_encode($params, 256);
        if (strlen($paramsJson) > 1024) {
            $paramsJson = '';
        }
        if (!in_array($params['type'], ['pdd.ktt.increment.order.query', 'pdd.ktt.order.list','pdd.ktt.after.sales.increment.list'], true)) {
            $log = new Log();
            $log->module = 'plat';
            $log->action = $method;
            $log->target_type = 2 . '--' . '花甜悦事';
            $log->target_id = 2;
            $log->target_field = $params['type'];
            $log->user_id = Auth::id() ?? 999;
            if ($size < 48000) {
                $log->message = json_encode($res, 256) . '=====' . $paramsJson;
            } else {
                $log->message = $paramsJson;
            }
            $log->save();
        }
        if (in_array($params['type'], ['pdd.ktt.increment.order.query', 'pdd.ktt.order.list','pdd.ktt.after.sales.increment.list'], true)) {
            LogFile::info('快团团请求: ' . $paramsJson);
            LogFile::info('快团团返回: ' . json_encode($res, 256));
        }

        return $res;
    }

    public function batchAsyncPostRequest($url, $batchParams)
    {
        $client = new Client();
        $promises = [];
        foreach ($batchParams as $param) {
            $options = [
                'headers' => ['Content-type' => 'application/x-www-form-urlencoded;'],
                'form_params' => $param
            ];
            $promises[] = $client->postAsync($url, $options);
        }
        if ($promises) {
            Promise\Utils::unwrap($promises);
        }
    }
}
