<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2099 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/mit-license.php )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace app\service;

use think\facade\Db;
use app\service\WarehouseService;
use app\service\GoodsService;

/**
 * 订单拆分服务层
 * @author  Devil
 * @blog    http://gong.gg/
 * @version 1.0.0
 * @date    2020-07-18
 * @desc    description
 */
class OrderSplitService
{
    /**
     * 订单拆分入口
     * @author  Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2020-07-18
     * @desc    description
     * @param   [array]           $params [输入参数]
     */
    public static function Run($params = [])
    {
        // 请求参数
        $p = [
            [
                'checked_type'      => 'is_array',
                'key_name'          => 'goods',
                'error_msg'         => MyLang('goods_empty_or_format_error_tips'),
            ],
        ];
        $ret = ParamsChecked($params, $p);
        if($ret !== true)
        {
            return DataReturn($ret, -1);
        }

        // 商品仓库集合
        $warehouse_goods = self::GoodsWarehouseAggregate($params);
        // 存在多个订单，但是订单模式非（快递、同城），则设置为快递模式
        if(count($warehouse_goods) > 1 && !in_array($params['site_model'], [0,1]))
        {
            $params['site_model'] = 0;
            $params['common_site_type'] = 0;
        }

        // 分组商品基础处理
        $data = self::GroupGoodsBaseHandle($warehouse_goods, $params);

        // 生成订单仓库分组商品数据处理钩子
        $hook_name = 'plugins_service_buy_group_goods_handle';
        $ret = EventReturnHandle(MyEventTrigger($hook_name, [
            'hook_name'     => $hook_name,
            'is_backend'    => true,
            'params'        => $params,
            'data'          => &$data,
        ]));
        if(isset($ret['code']) && $ret['code'] != 0)
        {
            return $ret;
        }

        // 根据扩展数据重新计算金额
        if(!empty($data))
        {
            foreach($data as &$v)
            {
                // 是否存在扩展数据
                if(!empty($v['order_base']['extension_data']))
                {
                    // 扩展数据金额计算
                    $ext = self::ExtensionDataPriceHandle($v['order_base']['extension_data']);

                    // 增加/减少
                    $v['order_base']['increase_price'] = PriceBeautify(PriceNumberFormat($v['order_base']['increase_price']+$ext['inc']));
                    $v['order_base']['preferential_price'] = PriceBeautify(PriceNumberFormat($v['order_base']['preferential_price']+$ext['dec']));

                    // 实际金额/总额处理
                    $v['order_base']['actual_price'] = PriceBeautify(PriceNumberFormat(($v['order_base']['actual_price']+$ext['inc'])-$ext['dec']));
                    $v['order_base']['total_price'] = PriceBeautify(PriceNumberFormat($v['order_base']['total_price']));

                    // 防止实际金额负数
                    if($v['order_base']['actual_price'] < 0)
                    {
                        $v['order_base']['actual_price'] = 0;
                    }
                }
            }
        }

        // 返回数据
        return DataReturn(MyLang('operate_success'), 0, $data);
    }

    /**
     * 扩展数据解析金额
     * @author  Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2020-07-23
     * @desc    description
     * @param   [array]          $data [扩展数据]
     */
    public static function ExtensionDataPriceHandle($data)
    {
        $inc = 0;
        $dec = 0;
        if(!empty($data))
        {
            if(!is_array($data))
            {
                $data = json_decode($data, true);
            }
            foreach($data as $v)
            {
                if(isset($v['type']) && isset($v['price']) && $v['price'] > 0)
                {
                    switch($v['type'])
                    {
                        // 减
                        case 0 :
                            $dec += $v['price'];
                            break;

                        // 加
                        case 1 :
                            $inc += $v['price'];
                            break;
                    }
                }
            }
        }
        return [
            'inc'   => $inc,
            'dec'   => $dec,
        ];
    }

    /**
     * 分组商品基础处理
     * @author  Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2020-07-23
     * @desc    description
     * @param   [array]          $data      [分组商品]
     * @param   [array]          $params    [输入参数]
     */
    public static function GroupGoodsBaseHandle($data, $params)
    {
        if(!empty($data))
        {
            foreach($data as &$v)
            {
                // 当前仓库的商品总价
                $total_price = PriceNumberFormat(array_sum(array_column($v['goods_items'], 'total_price')));

                // 订单基础信息
                $v['order_base'] = [
                    // 总价
                    'total_price'                       => PriceBeautify($total_price),
                    
                    // 订单实际支付金额(已减去优惠金额, 已加上增加金额)
                    'actual_price'                      => PriceBeautify($total_price),
                    
                    // 优惠金额
                    'preferential_price'                => 0.00,
                    
                    // 增加金额
                    'increase_price'                    => 0.00,
                    
                    // 商品总数
                    'goods_count'                       => count($v['goods_items']),
                    
                    // 规格重量总计
                    'spec_weight_total'                 => array_sum(array_map(function($v) {return $v['spec_weight']*$v['stock'];}, $v['goods_items'])),
                    
                    // 规格体积总计
                    'spec_volume_total'                 => array_sum(array_map(function($v) {return $v['spec_volume']*$v['stock'];}, $v['goods_items'])),
                    
                    // 购买总数
                    'buy_count'                         => array_sum(array_column($v['goods_items'], 'stock')),
                    
                    // 默认地址
                    'address'                           => $params['address'],
                    
                    // 自提地址列表
                    'extraction_address'                => $params['extraction_address'],
                    
                    // 当前使用的站点模式
                    'site_model'                        => $params['site_model'],
                    
                    // 公共站点模式
                    'common_site_type'                  => $params['common_site_type'],
                    
                    // 商品售价是否展示
                    'goods_price_show_status'           => (array_sum(array_filter(array_column($v['goods_items'], 'show_field_price_status'))) > 0) ? 1 : 0,

                    // 商品原价是否展示
                    'goods_original_price_show_status'  => (array_sum(array_filter(array_column($v['goods_items'], 'show_field_original_price_status'))) > 0) ? 1 : 0,

                    // 仓库组扩展展示数据
                    // name 名称
                    // price 金额
                    // type 类型（0减少, 1增加, 2其他）
                    // tips 提示信息
                    // images 图片
                    // url 链接地址
                    // business 业务类型（内容格式不限）
                    // ext 扩展数据（内容格式不限）
                    // is_buy_show 订单确认页面是否显示（0否，1是），默认显示
                    // $extension_data = [
                        // [
                        //     'name'       => '感恩节9折',
                        //     'price'      => 23,
                        //     'type'       => 0,
                        //     'tips'       => '-￥23元',
                        //     'business'   => null,
                        //     'ext'        => null,
                        // ],
                    // ];
                    'extension_data'                    => [],
                ];
            }
        }
        return $data;
    }

    /**
     * 商品仓库集合
     * @author  Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2020-07-18
     * @desc    description
     * @param   [array]          $params [输入参数]
     */
    public static function GoodsWarehouseAggregate($params)
    {
        // 仓库查询数据
        $field = 'w.*,wgs.inventory';
        $order_by = 'w.level desc,w.is_default desc,wgs.inventory desc';

        // 订单地址坐标
        $lng = '';
        $lat = '';
        if(!empty($params['address']))
        {
            if(isset($params['address']['lng']) && $params['address']['lng'] != 0 && isset($params['address']['lat']) && $params['address']['lat'] != 0)
            {
                $lng = $params['address']['lng'];
                $lat = $params['address']['lat'];
            }
        }
        // 没有地址坐标泽取当前用户坐标
        if(empty($lng) && empty($lat))
        {
            // 当前坐标
            $request_params = empty($params['params']) ? [] : $params['params'];
            $lng = empty($request_params['lng']) ? (empty($request_params['user_lng']) ? '' : $request_params['user_lng']) : $request_params['lng'];
            $lat = empty($request_params['lat']) ? (empty($request_params['user_lat']) ? '' : $request_params['user_lat']) : $request_params['lat'];
        }
        // 加入坐标优先级
        if(!empty($lng) && !empty($lat))
        {
            $field .= ',ROUND(6378.138*2*ASIN(SQRT(POW(SIN(('.$lat.'*PI()/180-w.lat*PI()/180)/2),2)+COS('.$lat.'*PI()/180)*COS(w.lat*PI()/180)*POW(SIN(('.$lng.'*PI()/180-w.lng*PI()/180)/2),2)))*1000) AS distance';
            $order_by = 'distance asc, '.$order_by;
        }

        // 默认仓库
        $warehouse_default = [];

        // 数据分组
        $result = [];
        foreach($params['goods'] as $v)
        {
            // 不存在规格则使用默认
            $spec = empty($v['spec']) ? [['type' => GoodsService::GoodsSpecDefaultName(),'value' => 'default']] : $v['spec'];

            // 获取商品库存、仓库商品壳仓库商品规格都必须等于当前商品
            $where = [
                ['wgs.goods_id', '=', $v['goods_id']],
                ['wgs.md5_key', '=', md5(implode('', array_column($spec, 'value')))],
                ['wgs.inventory', '>', 0],
                ['wg.goods_id', '=', $v['goods_id']],
                ['wg.is_enable', '=', 1],
                ['w.is_enable', '=', 1],
                ['w.is_delete_time', '=', 0],
            ];
            
            $warehouse = Db::name('WarehouseGoodsSpec')->alias('wgs')->join('warehouse_goods wg', 'wgs.warehouse_id=wg.warehouse_id')->join('warehouse w', 'wg.warehouse_id=w.id')->where($where)->field($field)->order($order_by)->select()->toArray();

            // 商品仓库分配仓库组合钩子
            $hook_name = 'plugins_service_buy_group_goods_warehouse_handle';
            MyEventTrigger($hook_name, [
                'hook_name'     => $hook_name,
                'is_backend'    => true,
                'params'        => $params,
                'spec'          => $spec,
                'where'         => $where,
                'goods'         => $v,
                'data'          => &$warehouse,
            ]);

            // 商品仓库分组
            if(!empty($warehouse))
            {
                foreach($warehouse as $w)
                {
                    // 是否还存在未分配的数量
                    if($v['stock'] > 0)
                    {
                        // 赋值数据
                        $temp_v = $v;

                        // 购买数量计算
                        if($temp_v['stock'] > $w['inventory'] && $w['inventory'] > 0)
                        {
                            $temp_v['stock'] = $w['inventory'];
                        }

                        // 总价计算
                        $temp_v['total_price'] = PriceBeautify(PriceNumberFormat(floatval($temp_v['price'])*$temp_v['stock']));

                        // 减除数量
                        $v['stock'] -= $w['inventory'];

                        // 是否第一次赋值
                        if(!array_key_exists($w['id'], $result))
                        {
                            // 仓库
                            unset($w['is_enable'], $w['is_delete_time'], $w['contacts_name'], $w['contacts_tel'], $w['add_time'], $w['upd_time']);
                            $warehouse_handle = WarehouseService::WarehouseListHandle([$w]);
                            $result[$w['id']] = $warehouse_handle[0];
                            $result[$w['id']]['goods_items'] = [];
                            unset($result[$w['id']]['is_default'], $result[$w['id']]['level'], $result[$w['id']]['inventory']);
                        }

                        // 商品归属到仓库下
                        $result[$w['id']]['goods_items'] = array_merge($result[$w['id']]['goods_items'], [$temp_v]);
                    } else {
                        break;
                    }
                }
            } else {
                // 未获取到仓库则使用默认仓库
                if(empty($warehouse_default))
                {
                    // 先获取默认仓库
                    $warehouse_default = Db::name('Warehouse')->where(['is_default'=>1, 'is_enable'=>1, 'is_delete_time'=>0])->field('id,name,alias,lng,lat,province,city,county,address')->find();
                    if(empty($warehouse_default))
                    {
                        // 没有默认仓库则获取最早的一个仓库
                        $warehouse_default = Db::name('Warehouse')->where(['is_enable'=>1, 'is_delete_time'=>0])->field('id,name,alias,lng,lat,province,city,county,address')->order('id asc')->find();
                    }
                }
                $temp_warehouse_default = $warehouse_default;

                // 商品仓库分配默认仓库组合钩子
                $hook_name = 'plugins_service_buy_group_goods_default_warehouse_handle';
                MyEventTrigger($hook_name, [
                    'hook_name'     => $hook_name,
                    'is_backend'    => true,
                    'params'        => $params,
                    'goods'         => $v,
                    'data'          => &$temp_warehouse_default,
                ]);

                // 存在默认仓库则继续分配
                if(!empty($temp_warehouse_default))
                {
                    if(!array_key_exists($temp_warehouse_default['id'], $result))
                    {
                        // 仓库
                        $warehouse_handle = WarehouseService::WarehouseListHandle([$temp_warehouse_default]);
                        $result[$temp_warehouse_default['id']] = $warehouse_handle[0];
                        $result[$temp_warehouse_default['id']]['goods_items'] = [];
                    }

                    // 商品归属到仓库下
                    $result[$temp_warehouse_default['id']]['goods_items'][] = $v;
                }
            }
        }
        return array_values($result);
    }
}
?>