<?php
declare (strict_types=1);

namespace app\admin\model;

use app\admin\common\YouZan;
use think\Exception;
use think\Model;

/**
 * @mixin \think\Model
 */
class OrderOutChild extends Model
{
    /**
     * @param string $outCode 发货单信息
     * @throws \Exception
     */
    static function makeChild(string $outCode = '')
    {
        if ($outCode == '') throw new \Exception("工单发货单单号不能为空");
        $out = self::name("order_out")->where(["outCode" => $outCode, "is_del" => 0])->findOrEmpty();
        if ($out->isEmpty()) throw new \Exception("发货单信息未找到");
        if ($out['send_status'] != 1) throw new \Exception("发货单拆单状态有误");
        $sale = self::name("sale")->where(["orderCode" => $out['orderCode'], "is_del" => 0])->findOrEmpty();
        if ($sale->isEmpty()) throw new \Exception("订单信息未找到");
        if ($sale['wsend_num'] < $out['send_num']) throw new \Exception("订单待发货数量不足");
        $num = $out['send_num'];
        $wsmlist = self::name("good_stock")->alias("a")
            ->leftJoin("warehouse_info b", "a.wsm_code=b.wsm_code")
            ->field("a.id,a.usable_stock,a.wait_out_stock,b.wsm_code,b.supplierNo,b.supplierName")
            ->where(["spuCode" => $sale['good_code'], "a.is_del" => 0,"b.wsm_type"=>[2,5], "b.companyNo" => $sale['supplierNo']])
            ->where("a.usable_stock", ">=", $num)
            ->order("a.usable_stock asc")
            ->findOrEmpty();
        $child = [
            "outChildCode" => '',
            "outCode" => $outCode,
            "orderCode" => $sale['orderCode'],
            "companyNo" => $sale['supplierNo'],
            "companyName" => $sale['supplierName'],
            "supplierNo" => $sale['supNo'],
            "supplierName" => $sale['supName'],
            "customer_code" => $sale['customer_code'],
            "customer_name" => $sale['customerName'],
            "spuCode" => $sale['good_code'],
            "skuCode" => $sale['skuCode'],
            "good_name" => $sale['good_name'],
            "order_type" => $sale['order_type'],
            "order_source" => $sale['order_source'],
            "num" => $num,
            "wsm_code" => $wsmlist['wsm_code'] ?? '',
            "apply_id" => $out['apply_id'],
            "apply_name" => $out['apply_name'],
            "addrid" => $out['addrid'],
            "status" => 1,
            "addtime" => date("Y-m-d H:i:s"),
            "updatetime" => date("Y-m-d H:i:s")
        ];
        if ($wsmlist->isEmpty()) self::BratchChild($child);
        else self::SingleChild($child, intval($wsmlist['id']));
        $outup = self::name("order_out")->where(["outCode" => $outCode, "is_del" => 0])->update(["send_status" => 2, "status" => 1, "updatetime" => date("Y-m-d H:i:s")]);
        if ($outup == false) throw new \Exception("发货单信息更新失败");
        return true;
    }

    /**单工单创建
     * @param array $child
     * @param int $wsm_id
     * @throws \think\Exception
     */
    public static function SingleChild(array $child = [], int $wsm_id = 0)
    {
        if (empty($child)) throw new Exception("发货工单信息不能为空");
        $child['outChildCode'] = makeNo("TCD");
        $childout = self::insertGetId($child);

        //生成发货工单的流程数据
        ProcessOrder::AddProcess(['id'=>request()->uid,'nickname'=>request()->uname], [
            "order_type" => 'FHGD',
            "order_code" => $child['outChildCode'],
            "order_id" => $childout,
            "order_status" => $child['status'] ?? 1,
            "before_status" => 0,
            'holder_id'=>$child['apply_id'],
        ]);

        if ($childout == false) throw new \Exception("发货工单生成失败");
        $bnadd = GoodStockInfo::ChildAddBn($child['outChildCode'], $wsm_id);
        if ($bnadd == false) throw new \Exception("库存更新失败");

    }

    /**多工单创建
     * @param array $child
     * @throws \think\Exception
     */
    public static function BratchChild(array $child = [])
    {

        if (empty($child)) throw new Exception("工单信息不能为空");
        $stock = self::name("good_stock")->alias("a")
            ->leftJoin("warehouse_info b", "a.wsm_code=b.wsm_code")
            ->where(["spuCode" => $child['spuCode'], "a.is_del" => 0,"b.wsm_type"=>[2,5], "b.companyNo" => $child['companyNo']])
            ->order("a.usable_stock desc")
            ->column("a.id,a.usable_stock,a.wait_out_stock,b.wsm_code,b.supplierNo,b.supplierName", "a.id");
        if (empty($stock)) throw new Exception("商品库存信息未找到");
        $wsmArr = self::GetKeyBySum($stock, intval($child['num']));
        if (empty($wsmArr)) throw new Exception("库存数不足生成工单");
        $i = 0;
        foreach ($wsmArr as $key => $val) {
            $i++;
            $child['outChildCode'] = substr(makeNo("TCD"), 0, -3) . str_pad(strval($i), 3, '0', STR_PAD_LEFT);
            $child['num'] = $val['desc_num'] ?? 0;
            $child['wsm_code'] = $val['wsm_code'];
            $childout = self::insertGetId($child);
            if ($childout == false) throw new \Exception("工单生成失败");

            //生成发货工单的流程数据
            ProcessOrder::AddProcess(['id'=>request()->uid,'nickname'=>request()->uname], [
                "order_type" => 'FHGD',
                "order_code" => $child['outChildCode'],//出库单号
                "order_id" => $childout,
                "order_status" => $child['status'] ?? 1,
                "before_status" => 0,
                'holder_id'=>$child['apply_id'],
            ]);

            $bnadd = GoodStockInfo::ChildAddBn($child['outChildCode'], intval($val['id']));
            if ($bnadd == false) throw new \Exception("库存更新失败");
        }
    }

    /**仓库选择
     * @param array $Arr
     * @param int $num
     * @return array
     * @throws \Exception
     */
    private static function GetKeyBySum(array $Arr = [], int $num = 0)
    {
        $resp = [];
        $keys = array_keys($Arr);
        $stock = array_column($Arr, "usable_stock");
        $newArr = array_combine($keys, $stock);
        if (array_sum($stock) < $num) throw new \Exception("库存数不足生成工单");
        foreach ($Arr as $key => $value) {
            if ($value['usable_stock'] >= $num) {
                $value['desc_num'] = $num;
                $num = 0;
            } else {
                $value['desc_num'] = $value['usable_stock'];
                $num -= $value['usable_stock'];
            }
            $resp[] = $value;
            if ($num == 0) break;
            unset($newArr[$key]);
            $k = array_search($num, $newArr);
            if ($k === false) continue;
            else {
                $Arr[$k]['desc_num'] = $num;
                $resp[] = $Arr[$k];
                break;
            }
        }
        return $resp;
    }

}