<?php

namespace common\helpers\bonus\Calc;

use common\helpers\bonus\PerfCalc;
use common\helpers\Cache;
use common\helpers\Date;
use common\helpers\snowflake\SnowFake;
use common\models\CalcRecord;
use common\models\DecOrder;
use common\models\forms\DeclarationForm;
use common\models\forms\OrderForm;
use common\models\Order;
use common\models\OrderDec;
use common\models\OrderShop;
use common\models\PerfOrder;
use common\models\Period;
use common\models\RemainPv;

/**
 * 生成业绩单相关表的数据 4张表写入1张业绩单表
 */
class GeneratePerfOrder extends BasePerfBusiness
{

    /**
     * @var array|mixed|\yii\db\ActiveRecord[]
     */
    private $_sysConfig;

    protected $_limit = 2000;

    public function __construct($periodNum)
    {
        parent::__construct($periodNum);
        $this->_sysConfig = Cache::getSystemConfig();//系统配置 AR_CONFIG

    }

    const BASE_INFO_METHODS = [
        //--- 业绩单表
        'perfOrder' => ['separately' => false, 'table' => 'AR_PERF_ORDER', 'field' => [
            'ID',
            'SN',
//            'PERF_TYPE',
            'DEC_TYPE',
            'USER_ID',
            'PV',
            'PERIOD_NUM',
            'CALC_MONTH',
            'DEC_USER_ID',
            'CREATED_AT',
            'ORDER_AMOUNT',
            'PAY_TYPE',
            'FROM_TABLE',
        ]],
    ];

    public function start(): array
    {
//        $this->setCalcStatus('start');
        try {
            //清除业务系统本地数据（业绩相关）
            $this->clearPerfOrderBusinessData();
            //清除并重新生成自动合格相关订单
            $this->_createFakeOrder($this->_periodNum, $this->_isCalcMonth);
            //生成业绩单
            $this->perfOrder();
            //todo 更新进度
//            $this->setCalcStatus('end');
            //如果自动结算 todo
            if (boolval($this->_sysConfig['autoCalcPeriod']['VALUE'])) {
//                $period = Period::instance();
//                if($period->isLastSent($this->_periodNum)) {
//                    $bonusCalc = BonusCalc::instance();
//                    $asyncResult = $bonusCalc->calcStep($this->_periodNum);
//                    if ($asyncResult) {
//                        $bonusCalc->endCalcTask();
//                    } else {
//                        $bonusCalc->errorCalcTask();
//                    }
//                    return $asyncResult;
//                }
            }

        } catch (\Exception $e) {
            $this->setCalcStatus('fail');
            return $this->fail('msg:' . $e->getMessage() . 'line:' . $e->getLine());
        }
        return $this->success();
    }

    public function clearPerfOrderBusinessData()
    {
        // 业绩单
        PerfOrder::pageDeleteAll('PERIOD_NUM=' . $this->_periodNum);
        CalcRecord::record($this->_periodNum, '【生成业绩单】业务系统，AR_PERF_ORDER表，本期数据已清空');
    }

    public function perfOrder(): bool
    {
        $this->decOrder();
        $this->orderDec();
        $this->order();
        $this->orderShop();
        return true;
    }

    public function decOrder(): bool
    {
        $_offset = 0;
        $countDecOrder = 0;
        decOrder:
        $allData = DecOrder::find()
            ->select('PAID_WALLET,ID,DEC_SN,ORDER_SN,USER_ID,TYPE,TO_USER_ID,IS_ADMIN,DEC_AMOUNT,DEC_PV,PERIOD_NUM,CALC_MONTH,IS_DEL,P_CALC_MONTH,CREATED_AT,DEC_ID')
            ->where("PERIOD_NUM=:PERIOD_NUM AND IS_DEL=0 AND TYPE='ZC'", [':PERIOD_NUM' => $this->_periodNum])
            ->orderBy('CREATED_AT DESC,ID DESC')
            ->limit($this->_limit)->offset($_offset * $this->_limit)
            ->with([
                'recName'        => function ($query) {
                    $query->select('USER_ID,REC_UID')
                        ->with([
                            'recUserName' => function ($query) {
                                $query->select('USER_ID,REC_UID,USER_NAME');
                            },
                            'recRealName' => function ($query) {
                                $query->select('ID,REAL_NAME');
                            }
                        ]);
                },
                'userByToUserId' => function ($query) {
                    $query->select('ID,LAST_DEC_LV,EMP_LV,STATUS,SUB_COM_ID,PROVINCE,CITY,COUNTY');
                },
                'userByUserId'   => function ($query) {
                    $query->select('ID,LAST_DEC_LV,SUB_COM_ID,PROVINCE,CITY,COUNTY');
                }
            ])
            ->asArray()->all();

        $insertPerfOrderData = [];
        if (!empty($allData)) {
            foreach ($allData as $k => $data) {
                $insertPerfOrderData[] = [
                    'LAST_REC_USER_NAME' => $data['recName']['recUserName']['USER_NAME'] ?? '',
                    'LAST_REC_REAL_NAME' => $data['recName']['recRealName']['REAL_NAME'] ?? '',
                    'LAST_DEC_LV'        => $data['userByToUserId']['LAST_DEC_LV'] ?? '', //CalcCache 810
                    'LAST_EMP_LV'        => $data['userByToUserId']['EMP_LV'] ?? '',
                    'LAST_STATUS'        => $data['userByToUserId']['STATUS'] ?? 0,
                    'LAST_SUB_COM_ID'    => $data['userByToUserId']['SUB_COM_ID'] ?? '',
                    'LAST_PROVINCE'      => $data['userByToUserId']['PROVINCE'] ?? 0,
                    'LAST_CITY'          => $data['userByToUserId']['CITY'] ?? 0,
                    'LAST_COUNTY'        => $data['userByToUserId']['COUNTY'] ?? 0,

                    'LAST_DEC_DEC_LV'     => $data['userByUserId']['LAST_DEC_LV'] ?? '',
                    'LAST_DEC_SUB_COM_ID' => $data['userByUserId']['SUB_COM_ID'] ?? 0,
                    'LAST_DEC_PROVINCE'   => $data['userByUserId']['PROVINCE'] ?? 0,
                    'LAST_DEC_CITY'       => $data['userByUserId']['CITY'] ?? 0,
                    'LAST_DEC_COUNTY'     => $data['userByUserId']['COUNTY'] ?? 0,

                    'PAY_TYPE'         => $data['PAID_WALLET'],
                    'FROM_TABLES'      => 'dec_order',
                    'ID'               => SnowFake::instance()->generateId(),
                    'SN'               => $data['ORDER_SN'],
                    'DEC_SN'           => $data['DEC_SN'],
                    'DEC_TYPE'         => strtoupper($data['TYPE']),
                    'DEC_STATUS'       => PerfOrder::STATUS_NORMAL,
                    'USER_ID'          => $data['TO_USER_ID'],
                    'PV'               => $data['DEC_PV'],
                    'DEC_AMOUNT'       => $data['DEC_AMOUNT'],
                    'DEC_USER_ID'      => $data['USER_ID'],
                    'PERIOD_NUM'       => $this->_periodNum,
                    'CALC_MONTH'       => $this->_calcYearMonth,
                    'P_CALC_MONTH'     => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH),
                    'CREATED_AT'       => Date::nowTime(),
                    'CLOSED_AT'        => 0,
                    'ORDER_CREATED_AT' => $data['CREATED_AT'],
                ];
            }
            $data    = null;
            $_offset += 1;
            $countDecOrder += count($insertPerfOrderData);
            $this->perfOrderInsert($insertPerfOrderData);
            $insertPerfOrderData = null;
            goto decOrder;
        }
        CalcRecord::record($this->_periodNum,"【生成业绩单】业务系统，AR_PERF_ORDER表，插入".$countDecOrder."条DecOrder记录");
        $allData = null;
        return true;
    }

    public function orderDec(): bool
    {
        $_offset = 0;
        $countOrderDec = 0;
        orderDec:
        $allData = OrderDec::find()->select(
            'PAY_TYPE,CREATED_AT,ID,SN,USER_ID,ORDER_TYPE,ORDER_AMOUNT,PV,PAY_AMOUNT,PAY_PV,PERIOD_NUM,PAY_TYPE')
            ->where("PERIOD_NUM=:PERIOD_NUM AND IS_DELETE=0 AND ORDER_TYPE=:ORDER_TYPE",
                [':PERIOD_NUM' => $this->_periodNum, ':ORDER_TYPE' => 'ZC'])
            ->orderBy('ID DESC')
            ->limit($this->_limit)->offset($_offset * $this->_limit)
            ->with([
                'recName'      => function ($query) {
                    $query->select('USER_ID,REC_UID')
                        ->with([
                            'recUserName' => function ($query) {
                                $query->select('USER_ID,REC_UID,USER_NAME');
                            },
                            'recRealName' => function ($query) {
                                $query->select('ID,REAL_NAME');
                            }
                        ]);
                },
                'userByUserId' => function ($query) {
                    $query->select('ID,DEC_ID,LAST_DEC_LV,EMP_LV,STATUS,SUB_COM_ID,PROVINCE,CITY,COUNTY');
                }
            ])
            ->asArray()->all();

        $insertPerfOrderData = [];
        if (!empty($allData)) {
            foreach ($allData as $k => $data) {
                $insertPerfOrderData[] = [
                    'LAST_REC_USER_NAME' => $data['recName']['recUserName']['USER_NAME'] ?? '',
                    'LAST_REC_REAL_NAME' => $data['recName']['recRealName']['REAL_NAME'] ?? '',
                    'LAST_DEC_LV'        => $data['userByUserId']['LAST_DEC_LV'] ?? '', //CalcCache 810
                    'LAST_EMP_LV'        => $data['userByUserId']['EMP_LV'] ?? '',
                    'LAST_STATUS'        => $data['userByUserId']['STATUS'] ?? 0,
                    'LAST_SUB_COM_ID'    => $data['userByUserId']['SUB_COM_ID'] ?? '',
                    'LAST_PROVINCE'      => $data['userByUserId']['PROVINCE'] ?? 0,
                    'LAST_CITY'          => $data['userByUserId']['CITY'] ?? 0,
                    'LAST_COUNTY'        => $data['userByUserId']['COUNTY'] ?? 0,

                    'LAST_DEC_DEC_LV'     => $data['userByUserId']['LAST_DEC_LV'] ?? '',
                    'LAST_DEC_SUB_COM_ID' => $data['userByUserId']['SUB_COM_ID'] ?? 0,
                    'LAST_DEC_PROVINCE'   => $data['userByUserId']['PROVINCE'] ?? 0,
                    'LAST_DEC_CITY'       => $data['userByUserId']['CITY'] ?? 0,
                    'LAST_DEC_COUNTY'     => $data['userByUserId']['COUNTY'] ?? 0,
                    'DEC_USER_ID'         => $data['userByUserId']['DEC_ID'],

                    'PAY_TYPE'         => $data['PAY_TYPE'],
                    'FROM_TABLES'      => 'order_dec',
                    'ID'               => SnowFake::instance()->generateId(),
                    'SN'               => $data['SN'],
                    'DEC_SN'           => $data['SN'],
                    'DEC_TYPE'         => strtoupper($data['ORDER_TYPE']),
                    'DEC_STATUS'       => PerfOrder::STATUS_NORMAL,
                    'USER_ID'          => $data['USER_ID'],
                    'PV'               => $data['PAY_PV'],
                    'DEC_AMOUNT'       => $data['ORDER_AMOUNT'],
                    'PERIOD_NUM'       => $this->_periodNum,
                    'CALC_MONTH'       => $this->_calcYearMonth,
                    'P_CALC_MONTH'     => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH),
                    'CREATED_AT'       => Date::nowTime(),
                    'CLOSED_AT'        => 0,
                    'ORDER_CREATED_AT' => $data['CREATED_AT']
                ];
            }
            $data    = null;
            $_offset += 1;
            $countOrderDec += count($insertPerfOrderData);
            $this->perfOrderInsert($insertPerfOrderData);
            $insertPerfOrderData = null;
            goto orderDec;
        }
        CalcRecord::record($this->_periodNum,"【生成业绩单】业务系统，AR_PERF_ORDER表，插入".$countOrderDec."条OrderDec记录");
        $allData = null;
        return true;
    }

    public function order(): bool
    {
        $_offset = 0;
        $countOrder = 0;
        order:
        $allData = Order::find()->select('ID,SN,DEC_SN,USER_ID,ORDER_TYPE,ORDER_AMOUNT,PAY_AMOUNT,PAY_PV,PAY_TYPE,PERIOD_NUM,STATUS,IS_DELETE,P_CALC_MONTH,CREATED_AT')
            ->where("PERIOD_NUM=:PERIOD_NUM AND IS_DELETE=0 AND ORDER_TYPE=:ORDER_TYPE",
                [':PERIOD_NUM' => $this->_periodNum, ':ORDER_TYPE' => DeclarationForm::TYPE_FX])
            ->orderBy('CREATED_AT DESC,ID DESC')
            ->limit($this->_limit)->offset($_offset * $this->_limit)
            ->with([
                'recName'      => function ($query) {
                    $query->select('USER_ID,REC_UID')
                        ->with([
                            'recUserName' => function ($query) {
                                $query->select('USER_ID,REC_UID,USER_NAME');
                            },
                            'recRealName' => function ($query) {
                                $query->select('ID,REAL_NAME');
                            }
                        ]);
                },
                'userByUserId' => function ($query) {
                    $query->select('ID,LAST_DEC_LV,EMP_LV,STATUS,SUB_COM_ID,PROVINCE,CITY,COUNTY');
                }
            ])
            ->asArray()->all();

        $insertPerfOrderData = [];
        if (!empty($allData)) {
            foreach ($allData as $k => $data) {
                if ($data['PAY_TYPE'] === PerfCalc::ORDER_PAY_TYPE_CASH) {
                    //111期开始由50%改为60%-by 2020-04-30修改
                    $payPv = $data['PAY_PV'] * $this->_sysConfig['cashReconsumeBonusPercent']['VALUE'] / 100;
                } else {
                    $payPv = $data['PAY_PV'];
                }

                if ($payPv <= 0) continue;

                $insertPerfOrderData[] = [
                    'PV'                 => $payPv,
                    'LAST_REC_USER_NAME' => $data['recName']['recUserName']['USER_NAME'] ?? '',
                    'LAST_REC_REAL_NAME' => $data['recName']['recRealName']['REAL_NAME'] ?? '',
                    'LAST_DEC_LV'        => $data['userByUserId']['LAST_DEC_LV'] ?? '', //CalcCache 810
                    'LAST_EMP_LV'        => $data['userByUserId']['EMP_LV'] ?? '',
                    'LAST_STATUS'        => $data['userByUserId']['STATUS'] ?? 0,
                    'LAST_SUB_COM_ID'    => $data['userByUserId']['SUB_COM_ID'] ?? '',
                    'LAST_PROVINCE'      => $data['userByUserId']['PROVINCE'] ?? 0,
                    'LAST_CITY'          => $data['userByUserId']['CITY'] ?? 0,
                    'LAST_COUNTY'        => $data['userByUserId']['COUNTY'] ?? 0,

                    'LAST_DEC_DEC_LV'     => $data['userByUserId']['LAST_DEC_LV'] ?? '',
                    'LAST_DEC_SUB_COM_ID' => $data['userByUserId']['SUB_COM_ID'] ?? 0,
                    'LAST_DEC_PROVINCE'   => $data['userByUserId']['PROVINCE'] ?? 0,
                    'LAST_DEC_CITY'       => $data['userByUserId']['CITY'] ?? 0,
                    'LAST_DEC_COUNTY'     => $data['userByUserId']['COUNTY'] ?? 0,
                    'DEC_USER_ID'         => $data['USER_ID'],

                    'PAY_TYPE'         => $data['PAY_TYPE'],
                    'FROM_TABLES'      => 'order',
                    'ID'               => SnowFake::instance()->generateId(),
                    'SN'               => $data['SN'],
                    'DEC_SN'           => null,
                    'DEC_TYPE'         => 'FX',
                    'DEC_STATUS'       => PerfOrder::STATUS_NORMAL,
                    'USER_ID'          => $data['USER_ID'],
                    'DEC_AMOUNT'       => $data['PAY_AMOUNT'],
                    'PERIOD_NUM'       => $this->_periodNum,
                    'CALC_MONTH'       => $this->_calcYearMonth,
                    'P_CALC_MONTH'     => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH),
                    'CREATED_AT'       => Date::nowTime(),
                    'CLOSED_AT'        => 0,
                    'ORDER_CREATED_AT' => $data['CREATED_AT']
                ];
            }
            $data    = null;
            $_offset += 1;
            $countOrder += count($insertPerfOrderData);
            $this->perfOrderInsert($insertPerfOrderData);
            $insertPerfOrderData = null;
            goto order;
        }
        CalcRecord::record($this->_periodNum,"【生成业绩单】业务系统，AR_PERF_ORDER表，插入".$countOrder."条Order记录");
        $allData = null;
        return true;
    }

    public function orderShop(): bool
    {
        $_offset = 0;
        $countOrderShop = 0;
        orderShop:
        $allData = OrderShop::find()->select(
            'ID,SN,DEC_SN,USER_ID,ORDER_TYPE,ORDER_AMOUNT,PAY_AMOUNT,PAY_PV,PAY_TYPE,
            PERIOD_NUM,STATUS,IS_DELETE,P_CALC_MONTH,CREATED_AT')
            ->where("PERIOD_NUM=:PERIOD_NUM AND IS_DELETE=0 AND ORDER_TYPE=:ORDER_TYPE",
                [':PERIOD_NUM' => $this->_periodNum, ':ORDER_TYPE' => DeclarationForm::TYPE_FX])
            ->orderBy('CREATED_AT DESC,ID DESC')
            ->limit($this->_limit)->offset($_offset * $this->_limit)
            ->with([
                'recName'      => function ($query) {
                    $query->select('USER_ID,REC_UID')
                        ->with([
                            'recUserName' => function ($query) {
                                $query->select('USER_ID,REC_UID,USER_NAME');
                            },
                            'recRealName' => function ($query) {
                                $query->select('ID,REAL_NAME');
                            }
                        ]);
                },
                'userByUserId' => function ($query) {
                    $query->select('ID,LAST_DEC_LV,EMP_LV,STATUS,SUB_COM_ID,PROVINCE,CITY,COUNTY');
                }
            ])
            ->asArray()->all();

        $insertPerfOrderData = [];
        if (!empty($allData)) {
            foreach ($allData as $k => $data) {
                if ($data['PAY_TYPE'] === PerfCalc::ORDER_PAY_TYPE_CASH) {
                    //111期开始由50%改为60%-by 2020-04-30修改
                    $payPv = $data['PAY_PV'] * $this->_sysConfig['cashReconsumeBonusPercent']['VALUE'] / 100;
                } else {
                    $payPv = $data['PAY_PV'];
                }

                if ($payPv <= 0) continue;

                $insertPerfOrderData[] = [
                    'PV'                 => $payPv,
                    'LAST_REC_USER_NAME' => $data['recName']['recUserName']['USER_NAME'] ?? '',
                    'LAST_REC_REAL_NAME' => $data['recName']['recRealName']['REAL_NAME'] ?? '',
                    'LAST_DEC_LV'        => $data['userByUserId']['LAST_DEC_LV'] ?? '', //CalcCache 810
                    'LAST_EMP_LV'        => $data['userByUserId']['EMP_LV'] ?? '',
                    'LAST_STATUS'        => $data['userByUserId']['STATUS'] ?? 0,
                    'LAST_SUB_COM_ID'    => $data['userByUserId']['SUB_COM_ID'] ?? '',
                    'LAST_PROVINCE'      => $data['userByUserId']['PROVINCE'] ?? 0,
                    'LAST_CITY'          => $data['userByUserId']['CITY'] ?? 0,
                    'LAST_COUNTY'        => $data['userByUserId']['COUNTY'] ?? 0,

                    'LAST_DEC_DEC_LV'     => $data['userByUserId']['LAST_DEC_LV'] ?? '',
                    'LAST_DEC_SUB_COM_ID' => $data['userByUserId']['SUB_COM_ID'] ?? 0,
                    'LAST_DEC_PROVINCE'   => $data['userByUserId']['PROVINCE'] ?? 0,
                    'LAST_DEC_CITY'       => $data['userByUserId']['CITY'] ?? 0,
                    'LAST_DEC_COUNTY'     => $data['userByUserId']['COUNTY'] ?? 0,

                    'DEC_USER_ID' => $data['USER_ID'],

                    'PAY_TYPE'         => $data['PAY_TYPE'],
                    'FROM_TABLES'      => 'order_shop',
                    'ID'               => SnowFake::instance()->generateId(),
                    'SN'               => $data['SN'],
                    'DEC_SN'           => null,
                    'DEC_TYPE'         => 'FX',
                    'DEC_STATUS'       => PerfOrder::STATUS_NORMAL,
                    'USER_ID'          => $data['USER_ID'],
                    'DEC_AMOUNT'       => $data['PAY_AMOUNT'],
                    'PERIOD_NUM'       => $this->_periodNum,
                    'CALC_MONTH'       => $this->_calcYearMonth,
                    'P_CALC_MONTH'     => Date::ociToDate($this->_calcYearMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH),
                    'CREATED_AT'       => Date::nowTime(),
                    'CLOSED_AT'        => 0,
                    'ORDER_CREATED_AT' => $data['CREATED_AT']
                ];
            }
            $data    = null;
            $_offset += 1;
            $countOrderShop += count($insertPerfOrderData);
            $this->perfOrderInsert($insertPerfOrderData);
            $insertPerfOrderData = null;
            goto orderShop;
        }
        CalcRecord::record($this->_periodNum,"【生成业绩单】业务系统，AR_PERF_ORDER表，插入".$countOrderShop."条OrderShop记录");
        $allData = null;
        return true;
    }


    /**
     * @param $data
     */
    private function perfOrderInsert($data)
    {
        $table = self::BASE_INFO_METHODS['perfOrder']['table'] ?? '';
//        $fieldArray = self::BASE_INFO_METHODS['perfOrder']['field'] ?? [];
        $fieldArray = array_keys($data[0]);
        return \Yii::$app->db->createCommand()->batchInsert($table, $fieldArray, $data)->execute();
    }

    public static function _createFakeOrder($periodNum, $isCalcMonth)
    {
        if ($isCalcMonth) {
            $periods = Period::getCurrentMonthPeriodByPeriodNum($periodNum);
            //先清除本期的假订单
//            echo('首先，清除上次尝试生成业绩单时所创建的虚假订单' . date('Y-m-d  H:i:s', time()) . PHP_EOL);
            Order::deleteAll(['IS_AUTO' => '1', 'PERIOD_NUM' => $periodNum]);
//            echo('检查有结余PV的用户，如果他当月PV不足30，则为其创建假订单' . PHP_EOL);
            $userHaveRemain = RemainPv::findAllAsArray('REMAIN_PV >0');
            foreach ($userHaveRemain as $uR) {
                $myPv = Order::find()->where(['PERIOD_NUM' => $periods, 'USER_ID' => $uR['USER_ID']])->SUM('PV');
                if ($myPv < self::$automaticEntitlementPerf) {
                    //制造虚拟订单
//                    echo('不足30了，生成假订单' . PHP_EOL);
                    $newOrderForm = new OrderForm();
                    $newOrderForm->addFakeOrder($uR['USER_ID'], $periodNum);
                }
            }
        }
    }
}

