<?php


namespace app\cxinv\controller;


use app\cxinv\model\ProductCheck;
use app\cxinv\model\ProductFz;
use app\cxinv\model\ProductsCombind;
use think\App;

class FinancialProducts extends Base
{
    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->model = new \app\cxinv\model\FinancialProducts();
    }

    public function List()
    {
        $param = $this->request->param(["skuCode" => "", "good_type" => "", "buyer_code" => "", "buyer_name" => "", "start" => "",
            "end" => "", "is_combind" => "", "basic_status" => "", "page" => 1, "size" => 15], "post", "trim");
        $where = [];
        if ($param['skuCode'] != "") $where[] = ["skuCode", "=", "%{$param['skuCode']}%"];
        if ($param['good_type'] != "") $where[] = ["good_type", "=", $param['good_type']];
        if ($param['buyer_code'] != "") $where[] = ["buyer_code", "=", $param['buyer_code']];
        if ($param['buyer_name'] != "") $where[] = ["buyer_name", "like", "%{$param['buyer_name']}%"];
        if ($param['start'] != "") $where[] = ["create_time", ">=", startTime($param['start'])];
        if ($param['end'] != "") $where[] = ["create_time", "<=", endTime($param['end'])];
        if ($param['is_combind'] != "") $where[] = ["is_combind", "=", $param['is_combind']];
        if ($param['basic_status'] !== "") $where[] = ["basic_status", "=", $param['basic_status']];
        $list = $this->model
            ->with(["catInfo", "ProductsCombind" => ['products'], "ProductStock"])
            ->where($where)
            ->order("id desc")
            ->paginate(['page' => $param['page'], 'list_rows' => $param['size']]);
        return success('获取成功', ['list' => $list->items(), 'count' => $list->total()]);
    }

    public function create()
    {
        $param = $this->request->param(["skuCode" => "", "goodName" => "", "good_type" => "", "buyer_code" => "", "buyer_name" => "",
            "seller_code" => "", "seller_name" => "", "good_source" => "", "inv_good_name" => "", "is_combind" => "", "spec" => "", "good_code" => "",
            "unit" => "", "unit_price" => "", "subunit_price" => "", "unit_weight" => "", "cat_code" => "", "cat_tax" => "", "inv_type" => "",
            "basic_status" => 1, 'spectral' => '', "childArr" => []], "post", "trim");
        $valid = $this->validate($param, [
            'skuCode|商品编号' => 'require|max:255',
            'goodName|商品名称' => 'require|max:255',
            'good_type|商品类型' => 'require|in:1,2,3',
            'buyer_code|买方公司纳税识别号' => 'require|max:255',
            'buyer_name|买方公司名称' => 'require|max:255',
            'seller_code|卖方公司纳税识别号' => 'require|max:255',
            'seller_name|卖方公司名称' => 'require|max:255',
            'good_source|商品来源' => 'require|in:1,2',
            'inv_good_name|发票商品名称' => 'require|max:255',
            'is_combind|是否组合商品' => 'require|in:0,1',
            'spec|规格' => 'max:255',
            'good_code|商品代码' => 'max:255',
            'unit|单位' => 'require|max:255',
            'unit_price|成本税前单价' => 'require|float',
            'subunit_price|成本税后单价' => 'require|float',
            'unit_weight|重量' => 'float',
            "spectral|分光" => 'max:255',
            'cat_code|进项类目' => 'require|max:255',
            'cat_tax|进项税率' => 'require|max:255',
            'inv_type|发票类型' => 'require|max:255',
            'basic_status|进项成本状态' => 'require|in:1,2',
            'childArr|商品子商品' => 'requireIf:is_combind,1|array'
        ]);
        if ($valid !== true) return error($valid);
        $param['apply_id'] = $this->uid;
        $param['apply_name'] = $this->uname;
        if ($param['is_combind'] == 1) {
            foreach ($param['childArr'] as $key => $item) {
                $iteminfo = $this->model->where('id', $item['child_id'])->findOrEmpty();
                if ($iteminfo->isEmpty()) return error("子商品{$iteminfo->skuCode}不存在");
                if ($item['child_num'] <= 0) return error("子商品{$iteminfo->skuCode}数量必须大于0");
                if ($iteminfo->basic_status == 2) return error("子商品{$iteminfo->skuCode}成本状态为预估成本");
            }
        }
        $where = $param;
        unset($where['childArr']);
        $isT = $this->model->where($where)->findOrEmpty();
        if (!$isT->isEmpty()) return error("商品编号{$param['skuCode']}已存在");
        $this->model->startTrans();
        try {
            $res = $this->model->create($param);
            if ($res->isEmpty()) throw new \Exception('添加失败');
            if ($param['is_combind'] == 1) {
                $parentid = $res->id;
                $childRes = (new ProductsCombind)->saveAll(array_map(function ($item) use ($parentid) {
                    $item['parent_id'] = $parentid;
                    return $item;
                }, $param['childArr']));
                if ($childRes->isEmpty()) throw new \Exception('添加失败');
            }
            $this->model->commit();
        } catch (\Exception $e) {
            $this->model->rollback();
            return error($e->getMessage());
        }

        return success('添加成功');
    }

    public function update()
    {
        $param = $this->request->param(["id" => "", "skuCode" => "", "goodName" => "", "good_type" => "", "buyer_code" => "", "buyer_name" => "",
            "seller_code" => "", "seller_name" => "", "good_source" => "", "inv_good_name" => "", "is_combind" => "", "spec" => "", "good_code" => "",
            "unit" => "", "unit_price" => "", "subunit_price" => "", "unit_weight" => "", "cat_code" => "", "cat_tax" => "", "inv_type" => "",
            "basic_status" => "", "childArr" => []], "post", "trim");
        $valid = $this->validate($param, [
            'id|商品ID' => 'require|integer',
            'skuCode|商品编号' => 'require|max:255',
            'goodName|商品名称' => 'require|max:255',
            'good_type|商品类型' => 'require|in:1,2,3',
            'buyer_code|买方公司纳税识别号' => 'require|max:255',
            'buyer_name|买方公司名称' => 'require|max:255',
            'seller_code|卖方公司纳税识别号' => 'require|max:255',
            'seller_name|卖方公司名称' => 'require|max:255',
            'good_source|商品来源' => 'require|in:1,2',
            'inv_good_name|发票商品名称' => 'require|max:255',
            'is_combind|是否组合商品' => 'require|in:0,1',
            'spec|规格' => 'max:255',
            'good_code|商品代码' => 'max:255',
            'unit|单位' => 'require|max:255',
            'unit_price|成本税前单价' => 'require|float',
            'subunit_price|成本税后单价' => 'require|float',
            'unit_weight|重量' => 'float',
            "spectral|分光" => 'max:255',
            'cat_code|进项类目' => 'require|max:255',
            'cat_tax|进项税率' => 'require|max:255',
            'inv_type|发票类型' => 'require|max:255',
            'basic_status|进项成本状态' => 'require|in:1,2',
            'childArr|商品子商品' => 'requireIf:is_combind,1|array'
        ]);
        if ($valid !== true) return error($valid);
        $info = $this->model->with(['ProductsCombind'])->findOrEmpty($param['id']);
        if ($info->isEmpty()) return error('数据不存在');
        if ($info->is_combind == 1 || $param['is_combind'] == 1) {
            $childIds = array_column($info->ProductsCombind->toArray(), "id");
            $paramChilds = array_column($param['childArr'], 'id');
            $delIds = array_diff($childIds, $paramChilds);
            $add = [];
            foreach ($param['childArr'] as $key => $item) {
                $iteminfo = $this->model->where('id', $item['child_id'])->findOrEmpty();
                if ($iteminfo->isEmpty()) return error("子商品{$iteminfo->skuCode}不存在");
                if ($item['child_num'] <= 0) return error("子商品{$iteminfo->skuCode}数量必须大于0");
                if ($iteminfo->basic_status == 2) return error("子商品{$iteminfo->skuCode}成本状态为预估成本");
                $item['id'] = $item['id'] ?? null;
                $item['parent_id'] = $param['id'];
                $add[] = $item;
            }
        }
        $where = $param;
        unset($where['childArr']);
        unset($where['id']);
        $isT = $this->model->where($where)->where("id", "<>", $param['id'])->findOrEmpty();
        if (!$isT->isEmpty()) return error("商品编号{$param['skuCode']}已存在");
        $this->model->startTrans();
        try {
            $res = $info->save($param);
            if (!$res) throw new \Exception('更新失败');
            if ($param['is_combind'] == 1) {
                if (!empty($delIds)) ProductsCombind::where(["parent_id" => $param['id'], "id" => $delIds])->delete();
                if (!empty($add)) {
                    $childRes = (new ProductsCombind)->saveAll($add);
                    if ($childRes->isEmpty()) throw new \Exception('更新失败');
                }
            }
            $this->model->commit();
        } catch (\Exception $e) {
            $this->model->rollback();
            return error($e->getMessage());
        }

        return success('更新成功');
    }

    public function info()
    {
        $id = $this->request->param("id", "0", "int");
        $info = $this->model->with(["catInfo", "ProductsCombind" => ['products'], 'ProductStock'])->findOrEmpty($id);
        if ($info->isEmpty()) return error('数据不存在');
        return success('获取成功', $info);
    }

    public function delete()
    {
        $id = $this->request->param("id", "0", "int");
        $info = $this->model->findOrEmpty($id);
        if ($info->isEmpty()) return error('数据不存在');
        $res = $info->delete();
        if ($info->is_combind == 1) {
            ProductsCombind::where("parent_id", $id)->delete();
        }
        return $res ? success('删除成功') : error('删除失败');
    }

    public function status()
    {
        $param = $this->request->param(["id" => "", "status" => ""], "post", "trim");
        $valid = $this->validate($param, [
            'id|商品ID' => 'require|integer',
            'status|状态' => 'require|in:0,1'
        ]);
        if ($valid !== true) return error($valid);
        $info = $this->model->findOrEmpty($param['id']);
        if ($info->isEmpty()) return error('数据不存在');
        $res = $info->save(['status' => $param['status']]);
        return $res ? success('修改成功') : error('修改失败');
    }

    public function getGoods()
    {
        $param = $this->request->param(["skuCode" => "", "good_type" => "", "buyer_code" => "", "seller_code" => "", "start" => "",
            "end" => "", "is_combind" => "", "basic_status" => "", "limit" => 100], "post", "trim");
        $valid = $this->validate($param, [
            'skuCode|商品编号' => 'max:255',
            'good_type|商品类型' => 'in:1,2,3',
            'buyer_code|买方公司纳税识别号' => 'max:255',
            'seller_code|卖方公司纳税识别号' => 'max:255',
            'start|开始时间' => 'date',
            'end|结束时间' => 'date',
            'is_combind|是否组合商品' => 'in:0,1',
            'basic_status|进项成本状态' => 'in:1,2',
        ]);
        if ($valid !== true) return error($valid);
        $where = [];
        if ($param['basic_status'] !== '') $where[] = ['basic_status', '=', $param['basic_status']];
        if (!empty($param['skuCode'])) $where[] = ['skuCode', 'like', '%' . $param['skuCode'] . '%'];
        if (!empty($param['good_type'])) $where[] = ['good_type', '=', $param['good_type']];
        if (!empty($param['buyer_code'])) $where[] = ['buyer_code', 'like', '%' . $param['buyer_code'] . '%'];
        if (!empty($param['seller_code'])) $where[] = ['seller_code', 'like', '%' . $param['seller_code'] . '%'];
        if (!empty($param['start']) && !empty($param['end'])) $where[] = ['create_time', 'between', [$param['start'], $param['end']]];
        $list = $this->model->with(['catInfo', 'ProductStock', 'ProductsCombind' => ['products']])->where($where)->order('id desc')->limit($param['limit'])->select();
        return success('获取成功', $list);
    }

    public function combindGood()
    {
        $param = $this->request->param(["parent_id" => "", "childArr" => []], "post", "trim");
        $valid = $this->validate($param, [
            'parent_id|商品ID' => 'require|integer',
            'childArr|子商品' => 'require|array'
        ]);
        if ($valid !== true) return error($valid);
        $parent = $this->model->findOrEmpty($param['pid']);
        if ($parent->isEmpty()) return error('数据不存在');
        $combind = new ProductsCombind();
        $ist = $combind->where(['parent_id' => $param['parent_id']])->column("child_id");
        $del = array_diff($ist, array_column($param['childArr'], 'child_id'));
        $add = [];
        foreach ($param['childArr'] as $item) {
            $vali = $this->validate($item, [
                'child_id|子商品ID' => 'require|integer',
                'child_num|子商品数量' => 'require|integer'
            ]);
            if ($vali !== true) return error($vali);
            $add[] = [
                "id" => $ist[$item['child_id']] ?? null,
                "parent_id" => $param['parent_id'],
                "child_num" => $item['child_num'],
                "child_id" => $item['child_id']
            ];
        }
        $this->model->startTrans();
        try {
            if (!empty($del)) $combind->where(["parent_id" => $param['parent_id'], "child_id" => $del])->delete();
            if (!empty($add)) $combind->saveAll($add);
            $this->model->commit();
        } catch (\Exception $e) {
            $this->model->rollback();
            return error($e->getMessage());
        }
        return success('修改成功');
    }

    public function CheckCreate()
    {
        $param = $this->request->param(["product_id" => "", 'check_num' => "", "check_type" => 0, "fz_date" => ""], "post", "trim");
        $valid = $this->validate($param, [
            'product_id|商品ID' => 'require|integer',
            'check_num|盘点数量' => 'require|float',
            'check_type|盘点类型' => 'require|in:0,1,2',
            'fz_date|调整单封账日期' => 'requireIf:check_type,2|max:255'
        ]);
        if ($valid !== true) return error($valid);
        $product = $this->model->with(['catInfo', 'ProductStock'])->findOrEmpty($param['product_id']);
        if ($product->isEmpty()) return error('商品数据不存在');
        if ($product->is_combind == 1) return error('组合商品不允许盘点');
        if ($param['check_type'] == 2) {
            $isT = ProductFz::where(["fz_date" => $param['fz_date'], "company_code" => $product->buyer_code])->findOrEmpty();
            if (!$isT->isEmpty() && $isT->status != 0) return error('该日期已封账,不允许再新增');
        }
        $diff_num = bcsub($param['check_num'], $product->residue_stock ?? "0", 8);
        if ($diff_num == 0) return error('盘点数量与库存数量一致,无需盘点');
        $is_diff = $diff_num > 0 ? 1 : 0;
        $data = [
            'checkCode' => makeNo("CWPD"),
            'product_id' => $param['product_id'],
            'check_num' => $param['check_num'],
            'diff_num' => $diff_num,
            'stock_num' => $product->residue_stock ?? "0",
            'unit_price' => $product->unit_price,
            'diff_fee' => bcmul($diff_num, $product->unit_price, 8),
            'check_type' => $param['check_type'],
            'fz_date' => $param['fz_date'],
            'is_diff' => $is_diff,
            "apply_id" => $this->uid,
            "apply_name" => $this->uname
        ];
        $this->model->startTrans();
        try {
            $use = ProductCheck::create($data);
            if ($use->isEmpty()) throw new \think\Exception("新增盘点单失败");
        } catch (\Exception $e) {
            $this->model->rollback();
            return error($e->getMessage());
        }
        $this->model->commit();
        return success('盘点单创建成功');
    }

    public function CheckBatch()
    {
        $list = $this->request->param("list", [], "trim");
        if (empty($list)) return error('请选择要批量盘点的商品');
        $create = [];
        foreach ($list as $item) {
            // product_id check_num balance_num check_type fz_date
            $valid = $this->validate($item, [
                'product_id|商品ID' => 'require|integer',
                'check_num|盘点数量' => 'require|float',
                'balance_num|库存数量' => 'require|float',
                'check_type|盘点类型' => 'require|in:0,1,2',
                'fz_date|调整单封账日期' => 'requireIf:check_type,2|max:255'
            ]);
            if ($valid !== true) return error($valid);
            $product = $this->model->with(['catInfo', 'ProductStock'])->findOrEmpty($item['product_id']);
            if ($product->isEmpty()) return error($item['product_id'] . '商品数据不存在');
            if ($product->is_combind == 1) return error($item['goodName'] . '组合商品不允许盘点');
            if ($item['check_type'] == 2) {
                $isT = ProductFz::where(["fz_date" => $item['fz_date'], "company_code" => $product->buyer_code])->findOrEmpty();
                if (!$isT->isEmpty() && $isT->status != 0) return error('该账期已封账,不允许再新增');
            }
            if ($item['balance_num'] != $product->residue_stock ?? "0") return error($product['goodName'] . '库存数量与盘点库存数量不一致');
            $diff_num = bcsub($item['check_num'], $item['balance_num'], 8);
            $isdiff = $diff_num > 0 ? 1 : 0;
            $create[] = [
                'checkCode' => makeNo("CWPD"),
                'product_id' => $item['product_id'],
                'check_num' => $item['check_num'],
                'diff_num' => $diff_num,
                'stock_num' => $product->residue_stock ?? "0",
                'unit_price' => $product->unit_price,
                'diff_fee' => bcmul($diff_num, $product->unit_price, 8),
                'check_type' => $item['check_type'],
                'fz_date' => $item['fz_date'],
                'is_diff' => $isdiff,
                "apply_id" => $this->uid,
                "apply_name" => $this->uname
            ];
        }
        $this->model->startTrans();
        try {
            $use = (new ProductCheck)->saveAll($create);
            if ($use->isEmpty()) throw new \think\Exception("批量新增盘点单失败");
            $this->model->commit();
        } catch (\Exception $e) {
            $this->model->rollback();
            return error($e->getMessage());
        }
        return success('批量盘点单创建成功');
    }

    public function CheckList()
    {
        $param = $this->request->param(["checkCode" => "", "check_type" => "", "start" => "", "end" => "", "skuCode" => "", "buyer_code" => "", "page" => 1, "size" => 20]
            , "post", "trim");
        $where = [];
        if ($param['checkCode'] !== "") $where[] = ['checkCode', 'like', '%' . $param['checkCode'] . '%'];
        if ($param['check_type'] !== "") $where[] = ['check_type', '=', $param['check_type']];
        if (!empty($param['start']) && !empty($param['end'])) $where[] = ['product_check.create_time', 'between', [startTime($param['start']), endTime($param['end'])]];
        if ($param['skuCode'] !== "") $where[] = ['product.skuCode', 'like', '%' . $param['skuCode'] . '%'];
        if ($param['buyer_code'] !== "") $where[] = ['product.buyer_code', '=', $param['buyer_code']];
        $list = ProductCheck::with(['product' => ['ProductStock']])
            ->withJoin(['product'], 'LEFT')
            ->where($where)
            ->order('id desc')
            ->paginate(['page' => $param['page'], 'list_rows' => $param['size']]);
        return success("获取成功", ["list" => $list->items(), "count" => $list->total()]);
    }

    public function CheckInfo()
    {
        $id = $this->request->param('id', 0, 'intval');
        if (empty($id)) return error('盘点单ID不能为空');
        $info = ProductCheck::with(['product' => ['ProductStock']])
            ->findOrEmpty($id);
        if ($info->isEmpty()) return error('盘点单不存在');
        return success("获取成功", $info);
    }
}