<?php


namespace common\services;


use common\components\AjaxException;
use common\models\AccidentCases;
use common\models\AccidentCasesStudy;
use common\models\BaseUser;
use common\models\EventOverview;
use common\util\AccidentCasesFocusObj;
use common\util\AccidentCasesObj;
use common\util\AccidentCasesScoreObj;
use common\util\EmergencyResponseObj;
use common\util\Holiday;
use yii\db\ActiveQuery;

class CaseService
{
    //因为案例数据使用了假删除，查询语句统一管理

    /**
     * @param $id
     * @return AccidentCases
     * @throws AjaxException
     */
    public static function getCaseById($id): AccidentCases
    {
        /** @var AccidentCases $AccidentCases */
        $AccidentCases = self::getCaseQuery()->andWhere(["id" => $id])->one();
        if (!$AccidentCases) {
            throw new AjaxException("案例不存在！");
        }
        return $AccidentCases;
    }

    /**
     * @return ActiveQuery
     */
    public static function getCaseQuery(): ActiveQuery
    {
        return AccidentCases::find()->where(["delete_time" => 0]);
    }

    public static function getCaseShowQuery(): ActiveQuery
    {
        return AccidentCases::find()->where(["delete_time" => 0, "status" => 1]);
    }

    /**
     * @throws AjaxException
     */
    public static function setCheckNameList($model, $checkList): void
    {
//        var_dump(isEmpty($checkList));exit;
        /** @var $model  AccidentCases */
        if ($checkList == []) {
            $model->check_name_list = "[]";
        } else {
            $checkNameList = [];
            $userList = array_column(UserService::getCanCheckList(), null, 'username');
            foreach ($checkList as $value) {
                if (isset($userList[$value])) {
                    $checkNameList[] = $userList[$value]->name;
                } else {
                    throw new AjaxException("审核人不符合要求！");
                }
            }
            $model->check_name_list = json_encode($checkNameList);
        }
    }

    /**
     * @throws AjaxException
     */
    public static function checkIsPublish($id, $userInfo): AccidentCases
    {
        //status 0 3 4可以修改
        $AccidentCases = self::getCaseById($id);
        if (!in_array($AccidentCases->status, [0, 4])) {
            throw new AjaxException("只能修改待审核和退回的案例！");
        }
        if ($AccidentCases->status === 1) {
            throw new AjaxException("发布中的案例无法操作！");
        }
        if ($AccidentCases->create_by != $userInfo->username) {
            if (!$userInfo->isSuperAdmin) {
                throw new AjaxException("只能操作自己创建的案例！");
            }
        }
        $AccidentCases->status = 0; //只要修改过了，自动变成待审核
        $AccidentCases->save();
        return $AccidentCases;
    }

    public static function deriveByAccidentCasesModel(AccidentCases $model): void
    {
        //万年历（日期、时间）；派生：[日期特征][时间特征]
        list($model->day_type, $model->time_type) = self::deriveByStartTime($model->start_time);
        //
        $DictionaryDeriveInfo = DictionaryRelationshipService::getDictionaryDeriveInfo();
        if ($model->train_number != null) {
            //车号；派生：[列车编组][车型][线路]
            list($model->train_group, $model->train_model) = self::deriveByTrainNumber($model->train_number, $DictionaryDeriveInfo);
        }
        if ($model->line != null) {
            //所属线路分类；派生：[自动化程度]；[信号系统供应商]
            list($model->automation_level, $model->signal_supplier) = self::deriveByLine($model->line, $DictionaryDeriveInfo);
        }
        //故障持续时长=故障/外部影响消除时间-事发时间
        $model->emergency_duration = ceil(($model->elimination_time - $model->start_time) / 60);
        //运营事件持续时长=运营基本恢复时间-事发时间
        $model->operation_duration = ceil(($model->recovery_time - $model->start_time) / 60);
    }

    /**
     * @param $start_time
     * @return int[] [$dayType, $timeType]
     */
    protected static function deriveByStartTime($start_time): array
    {
        return Holiday::getDayTypeAndTimeType($start_time);
    }

    protected static function deriveByTrainNumber($train_number, $DictionaryDeriveInfo = null): array
    {
        if (!$DictionaryDeriveInfo) {
            $DictionaryDeriveInfo = DictionaryRelationshipService::getDictionaryDeriveInfo();
        }
        $train_group = 0;
        $train_model = 0;
        $line = 0;
        $TrainNumberDeriveList = $DictionaryDeriveInfo[$train_number];
        foreach ($TrainNumberDeriveList as $TrainNumberDerive) {
            if ($TrainNumberDerive["param_name"] == "train_group") {
                $train_group = $TrainNumberDerive["relation_id"];
            } elseif ($TrainNumberDerive["param_name"] == "train_model") {
                $train_model = $TrainNumberDerive["relation_id"];
            } elseif ($TrainNumberDerive["param_name"] == "line") {
                $line = $TrainNumberDerive["relation_id"];
            }
        }
        return [$train_group, $train_model];
    }

    protected static function deriveByLine($line, $DictionaryDeriveInfo = null): array
    {
        if (!$DictionaryDeriveInfo) {
            $DictionaryDeriveInfo = DictionaryRelationshipService::getDictionaryDeriveInfo();
        }
        $automation_level = 0;
        $signal_supplier = 0;
        $lineDeriveList = $DictionaryDeriveInfo[$line];
        foreach ($lineDeriveList as $lineDerive) {
            if ($lineDerive["param_name"] == "automation_level") {
                $automation_level = $lineDerive["relation_id"];
            } elseif ($lineDerive["param_name"] == "signal_supplier") {
                $signal_supplier = $lineDerive["relation_id"];
            }
        }
        return [$automation_level, $signal_supplier];
    }

    /**
     * 获取案例详情
     * @param $id
     * @param string $type
     * @return array
     * @throws AjaxException
     */
    public static function getCaseDetail($id, string $type = "compare"): array
    {
        $AccidentCases = self::getCaseById($id);
//        $AccidentCases = self::checkIsPublish($id);
        self::dealWithCase($AccidentCases);
        list($totalScore, $emergencyResponseTotalScore, $operationalAdjustmentsTotalScore, $emergencyResponseScoreList, $operationalAdjustmentsScoreList) = AccidentCasesScoreService::getAccidentCasesDetailTotalSore($AccidentCases);
        $AccidentCases = $AccidentCases->attributes;
        $AccidentCases["totalScore"] = $totalScore;
        $AccidentCases["emergencyResponseTotalScore"] = $emergencyResponseTotalScore;
        $AccidentCases["operationalAdjustmentsTotalScore"] = $operationalAdjustmentsTotalScore;
        $AccidentCases["emergencyResponseScoreList"] = $emergencyResponseScoreList;
        $AccidentCases["operationalAdjustmentsScoreList"] = $operationalAdjustmentsScoreList;
        $AccidentCases["eventOverviewList"] = [];
        //查询原始资料
        $sourceDataList = array_column(EventSourceDataService::getSourceDataListByAccidentId($id), null, "id");
        /** @var EventOverview[] $eventOverviewList */
        $eventOverviewList = EventOverviewService::getEventOverviewQuery()->andWhere(["accident_id" => $AccidentCases["id"]])->orderBy('start_time asc,id asc')->all();
        foreach ($eventOverviewList as $eventOverview) {
            OperationalAdjustmentsService::dealWithSourceData($eventOverview, $sourceDataList);
            $AccidentCases["eventOverviewList"][] = $eventOverview;
        }
        $AccidentCases["emergencyResponseList"] = [];
        $emergencyResponseList = EmergencyResponseService::getEmergencyResponseQuery()->andWhere(["accident_id" => $AccidentCases["id"]])->orderBy('start_time asc,id asc')->all();
        EmergencyResponseService::listAddDimension($emergencyResponseList);
        foreach ($emergencyResponseList as $emergencyResponse) {
            OperationalAdjustmentsService::dealWithRules($emergencyResponse);
            OperationalAdjustmentsService::dealWithSourceData($emergencyResponse, $sourceDataList);
            $emergencyResponseObj = new EmergencyResponseObj($emergencyResponse);
            if ($type == "compare") {
                $AccidentCases["emergencyResponseList"][$emergencyResponse["type_first"]][] = $emergencyResponseObj;
                $AccidentCases["emergencyResponseList"][$emergencyResponse["type_second"]][] = $emergencyResponseObj;
            } else {
                $AccidentCases["emergencyResponseList"][] = $emergencyResponseObj;
            }
        }
        $AccidentCases["operationalAdjustmentsList"] = [];
        $operationalAdjustmentsList = OperationalAdjustmentsService::getQuery()->andWhere(["accident_id" => $AccidentCases["id"]])->orderBy('start_time asc,id asc')->all();
        OperationalAdjustmentsService::listAddDimension($operationalAdjustmentsList);
        foreach ($operationalAdjustmentsList as $operationalAdjustments) {
            OperationalAdjustmentsService::dealWithRules($operationalAdjustments);
            OperationalAdjustmentsService::dealWithSourceData($operationalAdjustments, $sourceDataList);
            $operationalAdjustmentsObj = new EmergencyResponseObj($operationalAdjustments);
            if ($type == "compare") {
                $AccidentCases["operationalAdjustmentsList"][$operationalAdjustments["type_first"]][] = $operationalAdjustmentsObj;
                $AccidentCases["operationalAdjustmentsList"][$operationalAdjustments["type_second"]][] = $operationalAdjustmentsObj;
            } else {
                $AccidentCases["operationalAdjustmentsList"][] = $operationalAdjustmentsObj;
            }
        }
        return $AccidentCases;
    }

    protected static function dealWithCase(AccidentCases $AccidentCases): void
    {
        //将数组从json转化出来
        $AccidentCases->type_base = json_decode($AccidentCases->type_base);
        $AccidentCases->type_first = json_decode($AccidentCases->type_first);
        $AccidentCases->type_second = json_decode($AccidentCases->type_second);
        $AccidentCases->type_third = json_decode($AccidentCases->type_third);
        $AccidentCases->type_extra = json_decode($AccidentCases->type_extra);
        $AccidentCases->position_base_second = json_decode($AccidentCases->position_base_second);
        $AccidentCases->position_extra_second = json_decode($AccidentCases->position_extra_second);
        $AccidentCases->substation_type = json_decode($AccidentCases->substation_type);
        $AccidentCases->duty_category = json_decode($AccidentCases->duty_category);
        $AccidentCases->duty_reason = json_decode($AccidentCases->duty_reason);
        $AccidentCases->check_list = json_decode($AccidentCases->check_list);
        $AccidentCases->check_name_list = json_decode($AccidentCases->check_name_list);
    }

    protected static function setTotalScore(AccidentCases $AccidentCases, $totalScoreList, $accidentId): void
    {
        //案例评分
        if (isset($totalScoreList[$accidentId])) {
            $AccidentCases->totalScore = new AccidentCasesScoreObj($totalScoreList[$accidentId]);
        } else {
            $AccidentCases->totalScore = null;
        }
    }

    public static function dealWithList($data): array
    {
        $newData = [];
        $accidentIds = array_column($data, "id");
        $totalScoreList = array_column(AccidentCasesScoreService::getTotalScoreList($accidentIds), null, "accident_id");
        foreach ($data as $key => $value) {
            /** @var AccidentCases $value */
            self::dealWithCase($value);
            self::setTotalScore($value, $totalScoreList, $value->id);
            $newData[] = new AccidentCasesObj($value);
        }
        return $newData;
    }

    public static function getTopCase($data)
    {

    }

    public static function dealWithFocusList($data): array
    {
        $newData = [];
        foreach ($data as $key => $value) {
            /** @var AccidentCases $value */
            $newData[] = new AccidentCasesFocusObj($value);
        }
        return $newData;
    }

    public static function study($id, BaseUser $userInfo)
    {
        $date = date("Y-m-d");
        $datetime = date("Y-m-d H:i:s");
        $studyInfo = AccidentCasesStudy::findOne(["accident_id" => $id, "uid" => $userInfo->id, "create_date" => $date]);
        if (!$studyInfo) {
            $studyInfo = new AccidentCasesStudy();
            $studyInfo->uid = $userInfo->id;
            $studyInfo->username = $userInfo->username;
            $studyInfo->name = $userInfo->name;
            $studyInfo->create_date = $date;
            $studyInfo->accident_id = $id;
            $studyInfo->learning_duration = 10;
            $studyInfo->last_learn_time = $datetime;
            $studyInfo->start_time = $datetime;
            $studyInfo->save();
        } else {
            if ($studyInfo->learning_duration < 1800) {
                //超过15秒以上，学习时间加10秒,同一个案例ID每天学习时长上限是30分钟。超过部分不予计算
                $studyInfo->learning_duration += 10;
                $studyInfo->last_learn_time = $datetime;
                $studyInfo->save();
            }
        }
    }

    public static function getCaseStudySqlSelectInfo(): string
    {
        return "a.title,s.uid,s.username,s.name,s.accident_id,s.learning_duration,s.create_date,s.start_time";
    }

    public static function setStudyTime($userInfoList): array
    {
        $listNew = [];
        foreach ($userInfoList as $userInfo){
            $startTime = date("Y-m-d H:i:s",strtotime("-30 days"));
            $totalCount = AccidentCasesStudy::find()->where(["uid" => $userInfo["id"]])->sum("learning_duration");
            $monthCount = AccidentCasesStudy::find()->where(["uid" => $userInfo["id"]])->andWhere([">=","start_time",$startTime])->sum("learning_duration");
            $userInfo["learning_duration"] = (int)$totalCount;
            $userInfo["learning_duration_month"] = (int)$monthCount;
            $listNew[] = $userInfo;
        }
        return $listNew;
    }
}