<?php
declare (strict_types = 1);

namespace app\command;
use app\apicom\model\SubAccountMoney;
use app\apicom\model\StockDealStock as DealStock;
use app\apicom\model\StockPosition;
use app\apicom\model\StockDeliveryOrder as Delivery;
 
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;

use util\RedisUtil;
use util\QuotationRedis;
use function Swoole\Coroutine\run;
use \co\Http\Client;

class Trust extends Command
{
    //protected $creteTime = sysConfig('trust_active_time') ??  TRUST_ACTIVE_TIME;

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

    protected function execute(Input $input, Output $output)
    {
        // 启动协程
    	swoole_timer_tick(1000, function (){
		    //if(!checkTradeTime()) return false;
		    $time  = sysConfig('trust_active_time')*60 ??  TRUST_ACTIVE_TIME;
    	    // 处理超时委托线程
    	    $res_c = Db::name('stock_trust')->where('status','已委托')->where("add_time", "<=", time() - $time)->select()->toArray();
		    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()->toArray();
    		if (!empty($res_t)) $this->goturnTrusts($res_t);
		});
		\Swoole\Event::wait();
    }
    /* 将最新委托转成不可撤销状态，等待交易 */
    protected function goturnTrusts($res){
		$this->output->writeln(date('Y-m-d H:i:s').' 交易委托: '.count($res)." 个");
		foreach ($res as $k => $item ){
			//查询股票最新行情
	        $Qdata = RedisUtil::getQuotationData($item['gupiao_code'],toMarket($item['gupiao_code']));
			Db::startTrans();
			if($this->checkTrust($item)){
			    if($item['info'] !== 'system'){
    			    switch ($item['flag1']) {
                        case 0; //'买入委托'
                            $eprice = QuotationRedis::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 = QuotationRedis::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)." 个");
		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    = SubAccountMoney::upMoneyLog($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    = SubAccountMoney::upMoneyLog($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)
    {
        //检查交割明细
        $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['Price']-$trust['trust_price']) * $trust['trust_count'], 2);
        //print_r($trust['sub_id'].' '.$affect.' '.$trustModel.' '.$Balance);return false;
        //写入子账户资金变化表
        $sm_res     = SubAccountMoney::upMoneyLog($trust['sub_id'], $affect, $trustModel , $return_money = 0, $Balance);
        //写入成交表
        $deal_res   = DealStock::add_m_deal_stock($Qdata,$trust['trust_count'],$trust['trust_price'],$trust['sub_id'],$trust['lid'],$trust['login_name'],$trust['soruce'],$trust['trust_no']);
        //查询持仓表
        $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  = StockPosition::add_m_position($trust['gupiao_code'],$canbuy,$trust['sub_id'],$trust['lid'],$trust['login_name'],$trust['soruce'],$trust['trust_price'],$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;
    }
    
}
