<?php namespace Seller\Lib;
use Dever;
use Dever\Helper\Str;
class Order
{
    # 新增订单
    public function add($info, $goods, $sku, $account, $order, $num = 1)
    {
        $data = Dever::store()->transaction(array($this, 'addAct'), array($info, $goods, $sku, $account, $order, $num), '下单失败');
        if ($data) {
            //\Dever\Helper\Redis::push('submit_' . $data['seller_id'], $data['id']);
            \Dever\Helper\Redis::push('submit_' . DEVER_PROJECT, $data['id']);
            Dever::load('info', 'seller')->log($data['seller_id'], $data['id'], $data['price'], 3);
        }
        return $data;
    }
    public function addAct($info, $goods, $sku, $account, $order, $num = 1)
    {
        # 验证规则
        $cate = Dever::db('cate', 'goods')->find($goods['cate_id']);
        if ($cate && $cate['rule'] && !preg_match($cate['rule'], $account)) {
            Dever::error($account . '不符合规则');
        }
        # 验证订单号
        $check = Dever::db('order', 'seller')->find(array('seller_id' => $info['id'], 'seller_order_num' => $order));
        if ($check) {
            Dever::error('订单重复');
        }

        $cash = $this->cash($info['id'], $sku['info_id'], $sku['id'], $sku['value'], $num);

        # 开始下单
        $data = array();
        $data['account'] = $account;
        $data['cate_id'] = $goods['cate_id'];
        $data['goods_id'] = $sku['info_id'];
        $data['sku_id'] = $sku['id'];
        $data['num'] = $num;
        $data['cash'] = $sku['value'];
        $data['price'] = $cash;
        $data['seller_id'] = $info['id'];
        $data['seller_order_num'] = $order;
        $data['seller_request'] = json_encode(Dever::input(), JSON_UNESCAPED_UNICODE);

        $data['id'] = Dever::db('order', 'seller')->insert($data);
        if (!$data['id']) {
            Dever::error('下单失败');
        }
        return $data;
    }

    public function handle($info, $selected = array())
    {
        $data = Dever::store()->transaction(array($this, 'handleAct'), array($info, $selected), '下单失败');
        $order = Dever::db('order', 'seller')->find($info['id']);
        if ($info['status'] < 10 && $order['status'] >= 10) {
            if ($order['status'] == 11) {
                # 失败，余额加回来
                Dever::load('info', 'seller')->inc($order['seller_id'], $order['price']);
                Dever::load('info', 'seller')->log($order['seller_id'], $order['id'], $order['price'], 4);
            }
            # 将记录写到influx中
            Dever::db('order_log', 'seller')->insert($order);
        }
        return $data;
    }

    public function handleAct($info, $selected = array())
    {
        if ($info['status'] >= 10) {
            return;
        }
        $update['status'] = 2;
        if (!$info['order_num']) {
            $info['order_num'] = $update['order_num'] = $this->createOrder();
        }
        Dever::db('order', 'seller')->update($info['id'], $update);

        $channel = $this->channel($info['seller_id'], $info['goods_id'], $info['sku_id']);
        if (!$channel) {
            return $this->notify($info, '通道未开启', $update);
        }
        $result = array();
        if ($channel['type'] == 1) {
            # 通信
            # 向渠道发起请求 下单
            $param['order_id'] = $info['id'];
            $param['order_num'] = $info['order_num'];
            $param['account'] = $info['account'];
            $param['cash'] = $info['cash'];
            $param['num'] = $info['num'];
            if ($info['other']) {
                $info['other'] = Dever::json_decode($info['other']);
                $param = array_merge($info['other'], $param);
            }
            if (isset($channel['goods']['code']) && $channel['goods']['code']) {
                $param['code'] = $channel['goods']['code'];
            } else {
                $sku = Dever::db('info_sku', 'goods')->find($info['sku_id']);
                $param['code'] = $sku['code'];
            }
            $result = Dever::load('func/api', 'connect')->run(1, $info['cate_id'], $channel, $param);
        } elseif ($channel['type'] == 2) {
            # 需要审核
            # 获取卡密并占用
            $param['seller_id'] = array('in', '-1,' . $info['seller_id']);
            $param['channel_id'] = $channel['id'];
            $param['goods_id'] = $info['goods_id'];
            $param['sku_id'] = $info['sku_id'];
            $param['status'] = 1;
            $param['use_status'] = 1;
            $card = Dever::db('card', 'channel')->select($param, array('order' => 'seller_id desc','limit' => '0, ' . $info['num']), true);
            $total = count($card);
            if ($total < $info['num']) {
                return $this->notify($info, '卡密剩余数量不足', $update);
            }
            foreach ($card as $k => $v) {
                Dever::db('card', 'channel')->update($v['id'], array('use_status' => 3, 'order_id' => $info['id']));
            }
            $result['status'] = 1;
        } elseif ($channel['type'] == 11) {
            $result['status'] = 1;
        }
        
        $update = array();
        $update['channel_id'] = $channel['id'];
        $update['channel_order_date'] = time();
        if (isset($result['request'])) {
            $update['channel_request'] = json_encode($result['request'], JSON_UNESCAPED_UNICODE);
        }
        if (isset($result['response'])) {
            $update['channel_response'] = json_encode($result['response'], JSON_UNESCAPED_UNICODE);
        }
        if (isset($channel['goods']['id'])) {
            $update['channel_goods_id'] = $channel['goods']['id'];
        }
        $update['channel_goods_discount'] = $channel['discount'];
        if (isset($channel['goods']['discount']) && $channel['goods']['discount']) {
            $update['channel_goods_discount'] = $channel['goods']['discount'];
        }
        if (!$update['channel_goods_discount']) {
            $update['channel_goods_discount'] = 1;
        }
        $update['buy_price'] = round($info['cash'] * $update['channel_goods_discount'], 2) * $info['num'];
        if ($result['status'] == 1) {
            # 下单成功
            Dever::db('order', 'seller')->update($info['id'], $update);
            return 'ok';
        } else {
            # 下单失败
            return $this->notify($info, '下单失败', $update);
        }
    }

    # 向商户发起回调
    public function notify($info, $msg, $update = array(), $total = 5)
    {
        $seller = Dever::db('info', 'seller')->find($info['seller_id']);
        $status = 11;
        if ($msg == 'ok') {
            $status = 10;
        }
        # 获取商户回调地址，向商户发起回调
        $seller_request = Dever::json_decode($info['seller_request']);
        if (isset($seller_request['notify']) && $seller_request['notify']) {
            $notify = $seller_request['notify'];
        } else {
            $notify = $seller['notify'];
        }
        if ($notify) {
            if ($info['seller_callback'] != 'ok' && $info['seller_callback_num'] <= $total) {
                $param = array();
                $param['appkey'] = $seller['appkey'];
                $param['order_num'] = $info['seller_order_num'];
                $param['system_order_num'] = $info['order_num'];
                $param['order_status'] = $status;
                $param['order_cash'] = $info['cash'];
                $param['official_order_num'] = $param['official_msg'] = '';
                if (isset($info['official_order_num'])) {
                    $param['official_order_num'] = $info['official_order_num'];
                }
                if (isset($info['official_msg'])) {
                    $param['official_msg'] = $info['official_msg'];
                }
                if (isset($update['official_order_num'])) {
                    $param['official_order_num'] = $update['official_order_num'];
                }
                if (isset($update['official_msg'])) {
                    $param['official_msg'] = $update['official_msg'];
                }

                $param = \Dever\Helper\Secure::get($param, $seller['appsecret']);
                $notify = urldecode($notify);
                $response = Dever::curl($notify, $param, 'post')->result();
                # ok是成功
                $update['seller_callback'] = $response;
                $update['seller_callback_date'] = time();
                $update['seller_callback_num'] = $info['seller_callback_num'] + 1;
            }
        } else {
            $update['seller_callback'] = 'ok';
            $update['seller_callback_date'] = time();
            $update['seller_callback_num'] = $info['seller_callback_num'] + 1;
        }
        $id = $info['id'];
        if ($info['status'] < 10 && $status >= 10) {
            # 订单完成
            $info['status'] = $update['status'] = $status;
            $update['finish'] = 1;
            $update['finish_date'] = time();
            $info = array_merge($info, $update);
            Dever::load('order', 'seller')->finish($info);
        }
        if (!$info['order_num']) {
            $update['order_num'] = $this->createOrder();
        }
        Dever::db('order', 'seller')->update($id, $update);
        return $msg;
    }

    public function finish($info)
    {
        if ($info['status'] == 10) {
            if ($info['channel_id']) {
                $channel = Dever::db('info', 'channel')->find($info['channel_id']);
                if (!$channel) {
                    Dever::error('未分配渠道');
                }
                if ($channel['type'] == 2) {
                    # 审核通过
                    $param['order_id'] = $info['id'];
                    //$param['status'] = 1;
                    $param['use_status'] = 3;
                    Dever::db('card', 'channel')->update($param, array('use_status' => 2));
                }
            }
        }
        if ($info['status'] == 11) {
            if ($info['channel_id']) {
                $channel = Dever::db('info', 'channel')->find($info['channel_id']);
                if (!$channel) {
                    Dever::error('未分配渠道');
                }
                if ($channel['type'] == 2) {
                    # 审核失败
                    $param['order_id'] = $info['id'];
                    //$param['status'] = 1;
                    $param['use_status'] = 3;
                    Dever::db('card', 'channel')->update($param, array('use_status' => 1));
                }
            }
            
            # 失败，余额加回来
            Dever::load('info', 'seller')->inc($info['seller_id'], $info['price']);
            Dever::load('info', 'seller')->log($info['seller_id'], $info['id'], $info['price'], 4);
        }

        /*
        $order_log = Dever::db('order_log', 'seller')->find(array('order_num' => $info['order_num']));
        if (!$order_log) {
            Dever::db('order_log', 'seller')->insert($info);
        }*/

        $order_log = Dever::db('order_log1', 'seller')->find(array('order_num' => $info['order_num']));
        if (!$order_log) {
            Dever::db('order_log1', 'seller')->insert($info);
        }
    }

    # 扣费
    public function cash($seller_id, $goods_id, $sku_id, $value, $num = 1)
    {
        if (!$value || $value <= 0) {
            Dever::error('面值无效');
        }
        
        # 查询折扣 扣费
        $seller_goods = Dever::db('goods', 'seller')->find(array('seller_id' => $seller_id, 'goods_id' => $goods_id, 'sku_id' => $sku_id));
        if (!$seller_goods) {
            $seller_goods = Dever::db('goods', 'seller')->find(array('seller_id' => $seller_id, 'goods_id' => $goods_id, 'sku_id' => -1));
        }

        $info = Dever::db('info', 'seller')->find($seller_id);
        if ($seller_goods && $seller_goods['discount']) {
            $info['discount'] = $seller_goods['discount'];
        }
        if (!$info['discount']) {
            $info['discount'] = 1;
        }
        $cash = round($value * $info['discount'], 2) * $num;

        # 查询余额是否充足
        $info['yue'] = $info['credit'] + $info['cash'];
        if ($info['yue'] < $cash) {
            Dever::error('余额不足');
        }
        $state = Dever::load('info', 'seller')->dec($info['id'], $cash);
        if (!$state) {
            Dever::error('余额不足');
        }
        return $cash;
    }

    # 获取渠道
    public function channel($seller_id, $goods_id, $sku_id, $selected = array())
    {
        # 查找渠道
        $channel_list = Dever::db('channel', 'seller')->select(array('seller_id' => $seller_id, 'goods_id' => $goods_id, 'status' => 1));
        if (!$channel_list) {
            return false;
        }
        $max = 1;
        $channel = $goods = array();
        foreach ($channel_list as $k => $v) {
            if ($selected && isset($selected[$v['channel_id']])) {
                continue;
            }
            if (!$v['sku_id']) {
                $goods = Dever::db('goods', 'channel')->find(array('channel_id' => $v['channel_id'], 'goods_id' => $goods_id, 'sku_id' => $sku_id));
                if ($goods) {
                    $channel = $v['channel_id'];
                    $max = $v['max'];
                    break;
                } else {
                    $goods = Dever::db('goods', 'channel')->find(array('channel_id' => $v['channel_id'], 'goods_id' => $goods_id, 'sku_id' => -1));
                    if ($goods) {
                        $channel = $v['channel_id'];
                        $max = $v['max'];
                        break;
                    }
                }
            } else {
                $all_sku_id = explode(',', $v['sku_id']);
                if (in_array($sku_id, $all_sku_id)) {
                    $channel = $v['channel_id'];
                    $max = $v['max'];
                    $goods = Dever::db('goods', 'channel')->find(array('channel_id' => $v['channel_id'], 'goods_id' => $goods_id, 'sku_id' => $sku_id));
                    if (!$goods) {
                        $goods = Dever::db('goods', 'channel')->find(array('channel_id' => $v['channel_id'], 'goods_id' => $goods_id, 'sku_id' => -1));
                    }
                    break;
                }
            }
        }
        if (!$channel) {
            return false;
        }

        $channel = Dever::db('info', 'channel')->find($channel);
        if (!$channel) {
            return false;
        }
        if ($channel['status'] == 2) {
            return false;
        }
        $channel['goods'] = $goods;
        $channel['max'] = $max;
        return $channel;
    }

    public function createOrder()
    {
        $where['order_num'] = Str::order('C');
        $state = Dever::db('order', 'seller')->find($where);
        if (!$state) {
            return $where['order_num'];
        } else {
            return $this->createOrder();
        }
    }
}