<?php
declare (strict_types = 1);

namespace app\market\command;
 
use app\market\model\Deal_stock;
use app\market\model\Position;
use app\market\model\SubAccountMoney;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;

use think\Db;

class TrustCommand extends Command
{

    protected function configure()
    {
        // 指令配置
        $this->setName('Trust')
            ->setDescription('交易脚本');
    }

    protected function execute(Input $input, Output $output)
    {
        // 启动协程
        //if(!checkTradeTime()) return false;
        $time  = config('trust_active_time')*60 ??  TRUST_ACTIVE_TIME;
        // 处理超时委托线程
        $res_c = Db::name('stock_trust')->where('status','已委托')->where("add_time", "<=", time() - $time)->select();
        if (!empty($res_c)) $this->cancelTrusts($res_c);
        // 处理委托交易线程
        //$res_t = Db::name('stock_trust')->where('status','已委托')->where("add_time", "between",[time() - $time, time()])->whereDay('trust_date')->select()->toArray();
        $res_t = Db::name('stock_trust')->where('status','已委托')->select();
        if (!empty($res_t)) $this->goturnTrusts($res_t);

    }

    /* 将最新委托转成不可撤销状态，等待交易 */
    protected function goturnTrusts($res){
		$this->output->writeln(date('Y-m-d H:i:s').' 交易委托: '.count($res)." 个");
		foreach ($res as $k => $item ){
			//查询股票最新行情
            $Qdata = z_market($item['gupiao_code']);
			Db::startTrans();
			if($this->checkTrust($item)){
			    if($item['info'] !== 'system'){
    			    switch ($item['flag1']) {
                        case 0; //'买入委托'
                            $eprice = self::getPrice($Qdata,$item['gupiao_code'],$item['trust_price'],'buy',$item['trust_count']);
                            if($eprice > 0){
                                $item['trust_price'] = $eprice;
                                $this->output->writeln(date('Y-m-d H:i:s').' '.$item['gupiao_name'].$item['gupiao_code'].' '.$item['trust_price'].' 买入价格：'.$eprice);
                                $order_res = $this->orderTrust($Qdata, $item, 6);//实盘买入模式：6
                            }else{
                			    $this->output->writeln(date('Y-m-d H:i:s').' '.$item['gupiao_name'].$item['gupiao_code'].' '.$item['trust_price'].' 价格检查：'.$eprice);
                			}
                            break;
                        case 1; //'卖出委托': 
            			    $eprice = self::getPrice($Qdata,$item['gupiao_code'],$item['trust_price'],'sell',$item['trust_count']);
            			    if($eprice > 0){ 
                			    $item['trust_price'] = $eprice;
                			    $this->output->writeln(date('Y-m-d H:i:s').' '.$item['gupiao_name'].$item['gupiao_code'].' '.$item['trust_price'].' 卖出价格：'.$eprice);
                			    $order_res = $this->orderTrust($Qdata, $item, 5);//实盘卖出模式：5
                			}else{
                			    $this->output->writeln(date('Y-m-d H:i:s').' '.$item['gupiao_name'].$item['gupiao_code'].' '.$item['trust_price'].' 价格检查：'.$eprice);
                			}
                            break;
                        default: $order_res = [];
                    }
			    }else{//如果是系统强制平仓就不检查市价
    			    $order_res = $this->orderTrust($Qdata, $item, 5);
    			}
			    if(isset($order_res) && !empty($order_res)){
                    //$this->output->writeln(date('Y-m-d H:i:s').' '.$item['gupiao_name'].$item['gupiao_code'].' 时间：'.date('H:i:s', $item['add_time']).' '.$item['trust_count'].'股 '.$item['flag2'].' 成交');
                    Db::commit();
                }else{
                    Db::rollback();
                    continue;
                }
			}else{
			    $this->output->writeln(date('Y-m-d H:i:s').' '.$item['gupiao_name'].$item['gupiao_code'].' 交易状态更新失败');
			}
		}
    }
    /* 撤销超时委托 */
    protected function cancelTrusts($res)
    {
		$this->output->writeln(date('Y-m-d H:i:s').' 超时委托: '.count($res)." 个");
        $subaccount=new SubAccountMoney();
		foreach ($res as $k => $v ){
			Db::startTrans();
            $info = Db::name('stock_trust')->where(['trust_no'=>$v['trust_no']])->lock(true)->find();
            if(!empty($info)){
                $row = [];
                $row['status'] = "已撤";
                $row['cancel_order_flag']  = 1;
                $row['cancel_order_count'] = $v['trust_count'];
                $trust  = Db::name('stock_trust')->where(['trust_no'=>$v['trust_no']])->update($row);
                $affect = Db::name('stock_delivery_order')->where(['trust_no'=>$v['trust_no']])->value('liquidation_amount');
                if(!$affect) {
                    $this->output->writeln(date('Y-m-d H:i:s').' 在订单数据库中，委托单号: '.$v['trust_no']." 没有找到");
                }

                switch ($info['flag2']){
                    case '买入委托':
                        //解冻并转入子账户可用余额
                        $subm_res    = $subaccount->up_moneylog($v['sub_id'], $affect, 8);
                        $position_in = $subm_res ? true : false;
                        break;
                    case '卖出委托':
                        $position    = Db::name('stock_position')->where(['sub_id'=>$v['sub_id'],'gupiao_code'=>$info['gupiao_code']])->find();
                        $position['canbuy_count'] = $position['canbuy_count']+$v['trust_count'];
                        $position_in = Db::name('stock_position')->where(['sub_id'=>$v['sub_id'],'gupiao_code'=>$info['gupiao_code']])->update($position);
                        $subm_res    = $subaccount->up_moneylog($v['sub_id'], $affect, 9);
                        break;
                }
                $delivery = Db::name('stock_delivery_order')->where(['trust_no'=>$v['trust_no']])->delete();
                
                if($trust && $delivery && $subm_res && $position_in){
                    Db::commit();
                }else{
                    Db::rollback();
                    continue;
                }
            }
            //$this->output->writeln(date('Y-m-d H:i:s').' '.$v['gupiao_name'].$v['gupiao_code'].' 时间：'.date('H:i:s', $v['add_time']).' '.$v['trust_count'].'股  撤单成功');
		}
    }
    /*写入委托表*/
    protected function checkTrust($item)
    {
        $row = [
           'status' => "已成",//状态说明
           'volume' => $item['trust_count'],//成交数量
           'amount' => $item['trust_count'] * $item['trust_price'],//成交金额
           'cancel_order_flag' => 1, //撤单标志 1、已成
        ];
		$trust  = Db::name('stock_trust')->where(['trust_no' => $item['trust_no']])->update($row);
		return $trust;
    }
    /*交易买入/卖出*/
    protected function orderTrust($Qdata, $trust, $trustModel)
    {
        $subaccount=new SubAccountMoney();
        //检查交割明细
        $dev_info   = Db::name('stock_delivery_order')->where(['trust_no'=>$trust['trust_no']])->find();
        //print_r($dev_info);return false;
        $affect     = $dev_info['liquidation_amount'];
		if(!$affect) return false;

        //$moneyinfo  = SubAccountMoney::getAccountMoney($trust['sub_id']);
        //计算佣金
		//$commission = commission($trust['trust_count'] * $trust['trust_price'],$moneyinfo['commission_scale'],$moneyinfo['min_commission']);
		//如果时卖出模式时加上印花税
		//$stamps     = $trustModel === 5 ? stamps($trust['trust_count'] * $trust['trust_price']) : 0;
		//计算过户费
		//$transfer   = transfer($trust['trust_count'] * $trust['trust_price']);
		//计算手续费
        //$fee        = $commission + $stamps + $transfer;
        //$cha        = $dev_info['commission'] + $dev_info['transfer_fee'] - $fee;
        
        //这里用(最新价格-委托价格*委托数量)，以便加入子账户中
        $Balance    = round(($Qdata['current_price']-$trust['trust_price']) * $trust['trust_count'], 2);
        //print_r($trust['sub_id'].' '.$affect.' '.$trustModel.' '.$Balance);return false;
        //写入子账户资金变化表
        $sm_res  = $subaccount->up_moneylog($trust['sub_id'], $affect, $trustModel , $return_money = 0, $Balance);
        //写入成交表
        $deal_stock = new Deal_stock();
        $deal_res   = $deal_stock->add_m_deal_stock($Qdata,$trust['trust_count'],$trust['trust_price'],$trust['sub_id'],$trust['lid'],$trust['login_name'],$trust['soruce'],$trust['trust_no'],1);
        //查询持仓表
        $postmd     = Db::name('stock_position')->where(['sub_id'=>$trust['sub_id'],'gupiao_code'=>$trust['gupiao_code']])->find();
        $canbuy     = !empty($postmd) ? $postmd['stock_count'] : 0;
        //if($canbuy <= 0) $this->output->writeln(date('Y-m-d H:i:s').$trust['gupiao_name'].' '.$trust['gupiao_code'].' 可卖数量: '.$canbuy);
        //组合数据后修改交割表
        $delivery = [];
        $position = [];
        switch ($trustModel) {
            case 6: //'买入委托' //实盘买入模式：6
                $delivery['amount'] = $canbuy + $trust['trust_count'];
                $delivery['amount'] = $canbuy + $trust['trust_count'];
                $canbuy = $canbuy + $trust['trust_count'];
                $this->output->writeln(date('Y-m-d H:i:s').$trust['gupiao_name'].' '.$trust['gupiao_code'].' 买入后数量: '.$canbuy);
                break;
            case 5: //'卖出委托' //实盘卖出模式：5
                $delivery['amount'] = $canbuy - $trust['trust_count'];
                $delivery['amount'] = $canbuy - $trust['trust_count'];
                $canbuy = $canbuy - $trust['trust_count'];
                $this->output->writeln(date('Y-m-d H:i:s').$trust['gupiao_name'].' '.$trust['gupiao_code'].' 卖出后数量: '.$canbuy);
                break;
            default: 
                $delivery['amount'] = $trust['trust_count'];
                $delivery['amount'] = $trust['trust_count'];
                break;
        }
        $delivery['status'] ='1';// 改变订单状态
        //$delivery['deal_price']         = $trust['trust_price'];
        //$delivery['deal_date']          = date("Y-m-d",time());
        //$delivery['transfer_fee']       = $transfer;
        //$delivery['commission']         = $commission;
        //$delivery['residual_quantity']  = $trust['trust_count'] * $trust['trust_price'];
        //$delivery['liquidation_amount'] = $trust['trust_count'] * $trust['trust_price'] + $fee;
        //$delivery['residual_amount']    = $dev_info['residual_amount'] + $dev_info['liquidation_amount'] - $delivery['liquidation_amount'];
        
        $delivery_res = Db::name('stock_delivery_order')->where(['trust_no'=>$trust['trust_no']])->update($delivery);
        // 新增/修改持仓列表
        $position_res  = Position::add_m_position($Qdata,$canbuy,$trust['sub_id'],$trust['lid'],$trust['login_name'],$trust['soruce'],$trust['trust_price'],2,$trust['trust_no']);
        //print_r($canbuy);return;
        if($sm_res && $deal_res && $delivery_res && $position_res) return true;
        $this->output->writeln(date('Y-m-d H:i:s').' sm_res: '.$sm_res." deal_res：".$deal_res." delivery_res：".$delivery_res." position_res：".$position_res);
        return false;
    }

    protected function getPrice($Qdata, $stockCode, $price, $direction, $count=100)
    {
        try {
            // 最新行情
            $eprice = 0;
            $Qdata  = $Qdata ?: z_market($stockCode);
            switch ($direction) {
                case 'buy':
                    if($price <= 0){
                        // 从1档递进取价格
                        for ($stall=1; $stall<=5; $stall++) {
                            switch ($stall) {
                                case 1: // 卖一
                                    $key = 'sell_one_price';//价格
                                    $val = 'sell_one_amount';//卖一量（手）
                                    break;
                                case 2: // 卖二
                                    $key = 'sell_two_price';//价格
                                    $val = 'sell_two_amount';//卖二量（手）
                                    break;
                                case 3: // 卖三
                                    $key = 'sell_three_price';//价格
                                    $val = 'sell_three_amount';//卖三量（手）
                                    break;
                                case 4: // 卖四
                                    $key = 'sell_four_price';//价格
                                    $val = 'sell_four_amount';//卖四量（手）
                                    break;
                                case 5: // 卖五
                                    $key = 'sell_five_price';//价格
                                    $val = 'sell_five_amount';//卖五量（手）
                                    break;
                            }
                            $price = $Qdata[$key];
                            if($price > 0 && $count <= $Qdata[$val]*10000){
                                $eprice = $price;
                                break;
                            }

                        }
                    }else{
                        $eprice = $price >= $Qdata['current_price'] && $Qdata['current_price'] > 0 && $price <= $Qdata['sell_five_price'] ? $price : 0;
                    }
                    break;
                case 'sell':
                    if($price <= 0){
                        // 从1档递进取价格
                        for ($stall=1; $stall<=5; $stall++) {
                            switch ($stall) {
                                case 1: // 卖一
                                    $key = 'buy_one_price';//价格
                                    $val = 'buy_one_amount';//卖一量（手）
                                    break;
                                case 2: // 卖二
                                    $key = 'buy_two_price';//价格
                                    $val = 'buy_two_amount';//卖二量（手）
                                    break;
                                case 3: // 卖三
                                    $key = 'buy_three_price';//价格
                                    $val = 'buy_three_amount';//卖三量（手）
                                    break;
                                case 4: // 卖四
                                    $key = 'buy_four_price';//价格
                                    $val = 'buy_four_amount';//卖四量（手）
                                    break;
                                case 5: // 卖五
                                    $key = 'buy_five_price';//价格
                                    $val = 'buy_five_amount';//卖五量（手）
                                    break;
                            }
                            $price = $Qdata[$key];
                            if($price > 0 && $count <= $Qdata[$val]*10000){
                                $eprice = $price;
                                break;
                            }
                        }
                    }else{
                        $eprice = $price <= $Qdata['current_price'] && $Qdata['current_price'] > 0 && $price <= $Qdata['buy_one_price'] ? $price : 0;
                    }
                    break;
            }
        } catch (\Exception $e) {
            $eprice = 0;
        }

        return $eprice;
    }
}
