<?php


namespace App\Services\goods;


use Api\PhpServices\Idgen\Idgen;
use Api\PhpServices\Ksy\Ks3Api;
use Api\PhpServices\Ksy\Ksyun;
use Api\PhpServices\Sensitive\Sensitive;
use Api\PhpUtils\Common\BaseConvert;
use Api\PhpUtils\Common\GoodsSkuId;
use Api\PhpUtils\Http\HttpUtil;
use Api\PhpUtils\Lock\FrequencyLockUtil;
use Api\PhpUtils\Log\FileLog;
use App\Exception\custom\GoodsException;
use App\Models\goods\mysql\Category;
use App\Models\goods\mysql\GoodsOperationRecord;
use App\Models\goods\mysql\GoodsRefundRecord;
use App\Models\goods\mysql\GoodsSku;
use App\Models\goods\mysql\GoodsSkuPicRecord;
use App\Models\goods\mysql\GoodsSkuSubShop;
use App\Models\goods\mysql\GoodsSnapshot;
use App\Models\goods\mysql\GoodsSpu;
use App\Models\goods\mysql\LifeAccountShopNum;
use App\Models\goods\mysql\Ota;
use App\Models\goods\mysql\PaySuccessGoodsCallbackRecord;
use App\Models\goods\mysql\PindanGoodsSku;
use App\Models\goods\mysql\PindanGoodsSnapshot;
use App\Models\goods\mysql\Shop;
use App\Models\marketing\mysql\Distributor;
use App\Models\marketing\mysql\Marketing;
use App\Models\marketing\mysql\MarketingGoods;
use App\Models\shop\mysql\SubShop;
use App\Services\marketing\DistributorService;
use App\Services\marketing\MarketingGoodsService;
use App\Services\marketing\MarketingService;
use App\Services\shop\ShopService;
use App\Services\common\CommonService;

use Api\PhpUtils\Http\Request;
use App\Exception\custom\InterfaceException;

class MarketingPindanGoodsService
{
    /**
     * 拼单商品
     * @param $params
     * @return string
     * @throws GoodsException
     * @throws \App\Exception\custom\CodeSpecialException
     */
    public static function pindanMarketingAddGoods($params)
    {
        GoodsSpu::beginTransaction();

        //生活号信息
        $params["life_account_id"] = MarketingService::getPublicLifeAccountId();

        //生活号信息
        $url = config('interface', 'merchant.lifeaccount.get_life_account_by_id');
        if (empty($url)) {
            throw new InterfaceException(['cus' => 0]);
        }
        $lifeAccountRes = HttpUtil::get($url, ["life_account_id" => $params["life_account_id"]]);
        if (empty($lifeAccountRes["response"]["result"])) {
            throw new GoodsException(['cus' => 29]);
        }

        $lifeAccount = [
            "life_account_id" => $params["life_account_id"],
            "merchant_id" => $lifeAccountRes["response"]["result"]["merchant_id"],
        ];

        $shopId = GoodsService::addShop($lifeAccount);
        $spuData = self::addGoodsSpu($shopId, $params);
        $skuId = self::addGoodsSku($spuData, $shopId, $params);
        //商品操作记录
        $record = [
            "goods_spu_id" => $spuData["goods_spu_id"],
            "goods_sku_id" => $skuId,
            "operator_id" => empty($params["publish_user_id"]) ? 0 : $params["publish_user_id"],
            "operator_name" => $params["user_name"],
            "goods_status" => GoodsSku::STATUS_PASS,
            "online_status" => GoodsSku::ONLINE_STATUS_ONLINE,
            "before_version" => 1,
            "after_version" => 1,
            "note" => empty($params["rejected_reason"]) ? "" : $params["rejected_reason"],
        ];
        GoodsOperationRecord::insertRecord($record);

        if (!GoodsSpu::commit()) {
            GoodsSpu::rollback();
            throw new GoodsException(["cus" => 0]);
        }

        $sku = PindanGoodsSku::getRecordMaster(["goods_sku_id" => $skuId]);
        $data = [];
        if (!empty($sku[0])) {
            $sku = $sku[0];
            $data["goods_info"] = $sku;
            $data["goods_info"]["original_price"] = empty($sku["original_price"]) ? '' : (string)($sku["original_price"] / 100);
            $data["goods_info"]["price"] = $sku["price"] / 100;
            $data["goods_info"]["desc_pic_url_list"] = [];
            if (!empty($sku["desc_pic_url"])) {
                $ksyun = GoodsService::getUrlList($sku["desc_pic_url"]);
                $data["goods_info"]["desc_pic_url_list"] = $ksyun;
            }
            $data["goods_info"]["ota_name"] = "";
            if (!empty($sku["ota_id"])) {
                $ota = Ota::getRecord(["ota_id" => $sku["ota_id"]], ["ota_name"]);
                if (!empty($ota)) {
                    $data["goods_info"]["ota_name"] = $ota["ota_name"];
                }
            }
        }
        return $data;
    }

    /**
     * 添加spu
     * @param $shopId
     * @param array $spuData
     * @return mixed
     * @throws GoodsException
     */
    private static function addGoodsSpu($shopId, $spuData = [])
    {
        $spu = GoodsSpu::get("*", ["goods_name" => $spuData["marketing_name"], "life_account_id" => $spuData["life_account_id"]]);
        if (!empty($spu)) {
            return $spu;
        }

        $res = GoodsService::getIdgenId(substr($shopId, -2), "goods");
        if (empty($res)) {
            throw new GoodsException(['cus' => 2]);
        }
        $spuId = $res[0];

        $spuParams = [
            "goods_spu_id" => $spuId,
            "shop_id" => $shopId,
            "life_account_id" => $spuData["life_account_id"],
            "publish_user_id" => $spuData["publish_user_id"],
            "goods_name" => $spuData["marketing_name"],
            "desc_pic_url" => $spuData["desc_pic_url"],
            "desc" => $spuData["desc"],
            "rule_limit" => empty($skuData["rule_limit"]) ? 0 : $skuData["rule_limit"],
            "goods_type" => empty($spuData["goods_type"]) ? GoodsSpu::TYPE_ENTITY : $spuData["goods_type"],
            "goods_sub_type" => empty($spuData["goods_sub_type"]) ? GoodsSpu::SUB_TYPE_INSTANT : $spuData["goods_sub_type"],
            "belong_type" => empty($spuData["belong_type"]) ? GoodsSpu::BELONG_TYPE_DISANFANG : $spuData["belong_type"],
            "goods_sale_type" => empty($spuData["setmeal"]) ? GoodsSpu::SALE_TYPE_NO_COMBINATION : GoodsSpu::SALE_TYPE_COMBINATION,
            "can_show_es" => GoodsSpu::CAN_SHOW_ES_NO,
        ];
        GoodsSpu::save($spuParams);
        return $spuParams;
    }

    /**
     * 添加拼单活动sku
     * @param $spuData
     * @param $shopId
     * @param array $skuData
     * @return string
     * @throws GoodsException
     * @throws \App\Exception\custom\CodeSpecialException
     */
    private static function addGoodsSku($spuData, $shopId, $skuData = [])
    {
        $res = GoodsService::getIdgenId(substr($shopId, -2), "goods");
        if (empty($res)) {
            throw new GoodsException(['cus' => 2]);
        }
        $skuId = GoodsSkuId::generateGoodSkuId($res[0], "00", "000", $spuData["goods_type"], $spuData["belong_type"], "001");

        if ($skuData["price"] <= 0) {
            throw new GoodsException(['cus' => 33]);
        }

        if ($skuData["price"] > 50000) {
            throw new GoodsException(['cus' => 34]);
        }
        $checkGoodsName = GoodsService::isHaveSensitive($skuData["goods_name"], 1);
        if ($checkGoodsName) {
            throw new GoodsException(['cus' => 19]);
        }
        $checkGoodsDesc = GoodsService::isHaveSensitive($skuData["desc"], 2);
        if ($checkGoodsDesc) {
            throw new GoodsException(['cus' => 20]);
        }
        
        //判断是否是整数
        if (!empty($skuData["rule_limit"]) && (!is_numeric($skuData["rule_limit"]) || strpos($skuData["rule_limit"], ".") !== false)) {
            throw new GoodsException(['cus' => GoodsException::RULE_LIMIT_ERROR]);
        }

        $skuParams = [
            "goods_sku_id" => $skuId,
            "goods_spu_id" => $spuData["goods_spu_id"],
            "life_account_id" => $skuData["life_account_id"],
            "publish_user_id" => empty($skuData["publish_user_id"]) ? "" : $skuData["publish_user_id"],
            "ota_id" => empty($skuData["ota_id"]) ? 0 : $skuData["ota_id"],
            "category_1_id" => 0,
            "category_2_id" => 0,
            "goods_name" => $skuData["goods_name"],
            "desc_pic_url" => $skuData["desc_pic_url"],
            "desc" => $skuData["desc"],
            "rule_limit" => empty($skuData["rule_limit"]) ? 0 : $skuData["rule_limit"],
            "inventory_total" => $skuData["inventory"],
            "inventory_rest" => $skuData["inventory"],
            "original_price" => empty($skuData["original_price"]) ? "" : $skuData["original_price"] * 100,
            "price" => $skuData["price"] * 100,
            "audit_status" => PindanGoodsSku::STATUS_PASS,
            "online_status" => PindanGoodsSku::ONLINE_STATUS_ONLINE,
        ];

        $res = PindanGoodsSku::save($skuParams);
        if ($res === false) {
            GoodsSpu::rollback();
            throw new GoodsException(["cus" => 0]);
        }
        GoodsService::addGoodsSkuPicRecord($skuId, $skuData);
        self::addPindanGoodsSnapshot($skuId);
        return $skuId;
    }

    /**
     * 编辑拼单商品
     * @param $params
     * @return bool
     * @throws GoodsException
     * @throws \App\Exception\custom\CodeSpecialException
     */
    public static function pindanMarketingEditGoods($params)
    {
        $goodsSkuId = $params["goods_sku_id"];
        $pindanGoodsSku = PindanGoodsSku::get("*", ["goods_sku_id" => $goodsSkuId]);
        if (empty($pindanGoodsSku)) {
            throw new GoodsException(["cus" => 15]);
        }

        GoodsSpu::beginTransaction();

        $goodsSpu = GoodsSpu::getRecord(["goods_spu_id" => $pindanGoodsSku["goods_spu_id"]]);

        self::editGoodsSpu($goodsSpu, $params);
        self::editGoodsSku($goodsSkuId, $pindanGoodsSku, $params);

        if (!GoodsSpu::commit()) {
            GoodsSpu::rollback();
            throw new GoodsException(["cus" => 0]);
        }

        return true;
    }

    /**
     * 编辑拼单spu
     * @param $goodsSpu
     * @param array $params
     * @return \Api\PhpUtils\Mysql\MysqlBase
     * @throws GoodsException
     */
    private static function editGoodsSpu($goodsSpu, $params = [])
    {
        return GoodsSpu::save([
            "desc_pic_url" => $params["desc_pic_url"],
            "desc" => $params["desc"],
            "rule_limit" => empty($params["rule_limit"]) ? 0 : $params["rule_limit"],
        ], ["goods_spu_id" => $goodsSpu["goods_spu_id"]]);
    }

    /**
     * 编辑拼单sku
     * @param $goodsSkuId
     * @param $skuData
     * @param array $params
     * @return \Api\PhpUtils\Mysql\MysqlBase
     * @throws GoodsException
     * @throws \App\Exception\custom\CodeSpecialException
     */
    private static function editGoodsSku($goodsSkuId, $skuData, $params = [])
    {
        $inventoryCount = $skuData["inventory_rest"] + $params["inventory_add"];
        $inventoryTotal = $skuData["inventory_total"] + $params["inventory_add"];

        if ($inventoryTotal < $skuData["inventory_lock"] + $skuData["total_amount_order"]) {
            throw new GoodsException(['cus' => 49]);
        }

        if ($inventoryCount < 0) {
            throw new GoodsException(['cus' => 18]);
        }
        $checkGoodsName = GoodsService::isHaveSensitive($params["goods_name"], 1);
        if ($checkGoodsName) {
            throw new GoodsException(['cus' => 19]);
        }
        $checkGoodsDesc = GoodsService::isHaveSensitive($params["desc"], 2);
        if ($checkGoodsDesc) {
            throw new GoodsException(['cus' => 20]);
        }

        if ($params["price"] <= 0) {
            throw new GoodsException(['cus' => 33]);
        }

        if ($params["price"] > 50000) {
            throw new GoodsException(['cus' => 34]);
        }

        //判断是否是整数
        if (!empty($params["rule_limit"]) && (!is_numeric($params["rule_limit"]) || strpos($params["rule_limit"], ".") !== false)) {
            throw new GoodsException(['cus' => GoodsException::RULE_LIMIT_ERROR]);
        }

        $skuParams = [
            "goods_name" => $params["goods_name"],
            "desc_pic_url" => $params["desc_pic_url"],
            "desc" => $params["desc"],
            "rule_limit" => empty($params["rule_limit"]) ? 0 : $params["rule_limit"],
            "inventory_total" => $inventoryTotal,
            "ota_id" => empty($params["ota_id"]) ? 0 : $params["ota_id"],
            "inventory_rest" => $inventoryCount,
            "original_price" => empty($params["original_price"]) ? "" : $params["original_price"] * 100,
            "price" => $params["price"] * 100,
            "goods_version" => (int)$skuData["goods_version"] + 1,
        ];

        //商品操作记录
        $record = [
            "goods_spu_id" => $skuData["goods_spu_id"],
            "goods_sku_id" => $goodsSkuId,
            "operator_id" => empty($params["publish_user_id"]) ? 0 : $params["publish_user_id"],//op后台操作没有记录user_id
            "operator_name" => $params["user_name"],
            "goods_status" => GoodsSku::STATUS_PASS,
            "online_status" => GoodsSku::ONLINE_STATUS_ONLINE,
            "before_version" => $skuData["goods_version"],
            "after_version" => $skuParams["goods_version"],
            "note" => empty($params["rejected_reason"]) ? "" : $params["rejected_reason"],
        ];
        GoodsOperationRecord::insertRecord($record);

        GoodsService::addGoodsSkuPicRecord($goodsSkuId, $skuParams);

        $pindanGoodsSkuRes = PindanGoodsSku::save($skuParams, ["goods_sku_id" => $goodsSkuId]);
        if (!empty($pindanGoodsSkuRes)) {
            self::addPindanGoodsSnapshot($goodsSkuId);
        }
        return $pindanGoodsSkuRes;
    }

    /**
     * 拼单商品快照
     * @param $skuId
     */
    private static function addPindanGoodsSnapshot($skuId)
    {
        $skuInfo = PindanGoodsSku::getRecordMaster(["goods_sku_id" => $skuId]);
        PindanGoodsSnapshot::insertRecord($skuInfo[0]);
    }

    /**
     * 拼单商品商品快照
     * @param $params
     * @return array
     * @throws GoodsException
     */
    public static function pindanGoodsSnapshotInfo($params)
    {
        $data = [];
        $goodsSnapshot = PindanGoodsSnapshot::getRecord(["goods_sku_id" => $params["goods_sku_id"], "goods_version" => $params["version"]]);
        if (empty($goodsSnapshot)) {
            throw new GoodsException(["cus" => 23]);
        }

        $data["goods_name"] = $goodsSnapshot["goods_name"];
        $data["desc_pic_url_list"] = [];
        if (!empty($goodsSnapshot["desc_pic_url"])) {
            $ksyun = GoodsService::getUrlList($goodsSnapshot["desc_pic_url"]);
            $data["desc_pic_url_list"] = $ksyun;
        }

        $data["desc"] = $goodsSnapshot["desc"];
        $data["original_price"] = $goodsSnapshot["original_price"] / 100;
        $data["price"] = $goodsSnapshot["price"] / 100;
        return $data;
    }

    /**
     * 拼单商品后台搜商品
     * @param $params
     * @return array
     */
    public static function getPindanGoodsList($params)
    {
        $params['goods_sku_ids'] = !empty($params['goods_sku_ids']) ? $params['goods_sku_ids'] : "";
        $params['page'] = !empty($params['page']) ? $params['page'] : 1;
        $limit = !empty($params['page_size']) ? $params['page_size'] : 20;
        $page = ($params['page'] - 1) * $limit;

        $where = $data = [];
        if (!empty($params["ota_id"])) {
            $where["ota_id"] = $params["ota_id"];
        }
        if (!empty($params["goods_name"])) {
            $where["goods_name[~]"] = $params["goods_name"];
        }
        if (!empty($params["goods_sku_ids"])) {
            $where["goods_sku_id"] = explode(",", $params["goods_sku_ids"]);
        }

        $where['LIMIT'] = [$page, $limit];
        $where['ORDER'] = ["update_time" => "DESC"];

        $list = PindanGoodsSku::select("*", $where);
        $otaData = [];
        if (!empty($list)) {
            $otaIds = array_unique(array_column($list, "ota_id"));
            $otaList = Ota::select(["ota_id", "ota_name"], ["ota_id" => $otaIds]);
            if (!empty($otaList)) {
                foreach ($otaList as $item) {
                    $otaData[$item["ota_id"]] = $item;
                }
            }
        }
        $count = PindanGoodsSku::count("*", $where);
        if (!empty($list)) {
            foreach ($list as $key => $item) {
                $list[$key]["original_price"] = (int)$item["original_price"] / 100;
                $list[$key]["price"] = $item["price"] / 100;
                if (!empty($otaData) && !empty($otaData[$item["ota_id"]])) {
                    $list[$key]["ota_name"] = $otaData[$item["ota_id"]]["ota_name"];
                }
                $ksyun = GoodsService::getUrlList($item["desc_pic_url"]);
                $list[$key]["desc_pic_url_list"] = $ksyun;
            }
        }

        return ["list" => $list, "count" => $count];
    }

    /**
     * 获取拼单商品详情
     * @param $params
     * @return array
     * @throws GoodsException
     */
    public static function pindanGoodsInfo($params)
    {
        $data = [];
        $sku = PindanGoodsSku::get("*", ["goods_sku_id" => $params["goods_sku_id"]]);
        if (empty($sku)) {
            throw new GoodsException(["cus" => 15]);
        }

        $data["goods_info"] = $sku;
        $data["goods_info"]["original_price"] = empty($sku["original_price"]) ? '' : (string)($sku["original_price"] / 100);
        $data["goods_info"]["price"] = $sku["price"] / 100;
        $data["goods_info"]["desc_pic_url_list"] = [];
        if (!empty($sku["desc_pic_url"])) {
            $ksyun = GoodsService::getUrlList($sku["desc_pic_url"]);
            $data["goods_info"]["desc_pic_url_list"] = $ksyun;

            $strList = explode(",", $sku["desc_pic_url"]);
            $shareStr = $strList[0];
            $shareRes = Ks3Api::picEncryptUrl($shareStr, 500, 400);
            $shareUrl = empty($shareRes["response"]["data"]["url"]) ? "" :  $shareRes["response"]["data"]["url"];
            $data["goods_info"]["share_url"] = $shareUrl;
        }
        return $data;
    }

    /**
     * 退款拼单商品，库存调整
     * @param $params
     * @return bool
     * @throws GoodsException
     */
    public static function refundGoods($params)
    {
        $sku = PindanGoodsSku::get("*", ["goods_sku_id" => $params["goods_sku_id"]]);
        if (empty($sku)) {
            throw new GoodsException(["cus" => 15]);
        }

        PindanGoodsSku::beginTransaction();

        $records = GoodsRefundRecord::getRecordMaster([
            "goods_sku_id" => $params["goods_sku_id"],
            "order_item_id" => $params["order_item_id"],
            "operator_result" => GoodsRefundRecord::OPERATOR_RESULT_SUCCESS
        ]);
        if (empty($records)) {
            GoodsRefundRecord::save([
                "goods_sku_id" => $params["goods_sku_id"],
                "order_id" => $params["order_id"],
                "order_item_id" => $params["order_item_id"],
                "num" => $params["num"],
                "operator_result" => GoodsRefundRecord::OPERATOR_RESULT_SUCCESS
            ]);

            $row = PindanGoodsSku::save([
                "total_amount_sold[-]" => $params["num"],
                "total_amount_order[-]" => $params["num"],
                "inventory_rest[+]" => $params["num"],
                ], ["goods_sku_id" => $sku["goods_sku_id"], "total_amount_sold[>=]" => $params["num"], "total_amount_order[>=]" => $params["num"]]);

            FileLog::info('goods_refund_log', 'json decode error raw:' . json_encode($params));

            if ($row < 1){
                PindanGoodsSku::rollback();
                GoodsRefundRecord::save([
                    "goods_sku_id" => $params["goods_sku_id"],
                    "order_id" => $params["order_id"],
                    "order_item_id" => $params["order_item_id"],
                    "num" => $params["num"],
                    "operator_result" => GoodsRefundRecord::OPERATOR_RESULT_FAILURE
                ]);
                throw new GoodsException(["cus" => 0]);
            }
        }

        if (!PindanGoodsSku::commit()) {
            PindanGoodsSku::rollback();
            throw new GoodsException(["cus" => 0]);
        }
        return true;
    }
}