<?php


namespace common\services;


use common\components\AjaxException;
use common\models\AccidentCases;
use common\models\AccidentCasesScore;
use common\models\AccidentCasesScoreConfig;
use common\util\AccidentCasesDimensionObj;
use common\util\AccidentCasesScoreObj;
use common\util\CalculateTotalScoreObj;
use Yii;
use yii\db\ActiveRecord;
use yii\db\Exception;

class AccidentCasesScoreService
{
    public static int $totalScore = 1;

    public static int $EmergencyResponseTotalCategory = 2;

    public static int $EmergencyResponseCategory = 3;

    public static int $OperationalAdjustmentsTotalCategory = 4;

    public static int $OperationalAdjustmentsCategory = 5;

    public static function getCategoryList()
    {
        return [
            self::$totalScore => [0],
            self::$EmergencyResponseTotalCategory => [247],
            self::$EmergencyResponseCategory => [248, 249, 250, 251, 252, 253],
            self::$OperationalAdjustmentsTotalCategory => [346],
            self::$OperationalAdjustmentsCategory => [347, 348],
        ];
    }

    public static function getContentDictionaryIdList($categoryList = [])
    {
        if ($categoryList == []) {
            $categoryList = self::getCategoryList();
        }
        return array_merge($categoryList[self::$EmergencyResponseTotalCategory], $categoryList[self::$EmergencyResponseCategory], $categoryList[self::$OperationalAdjustmentsTotalCategory], $categoryList[self::$OperationalAdjustmentsCategory]);
    }

    public static function initScore($accidentId): void
    {
        $param = [
            "accident_id",
            "dictionary_id",
            "category",
            "content",
            "content_two",
            "score",
            "update_time"
        ];
        $time = time();
        $paramData = [];
        $categoryList = self::getCategoryList();
        foreach ($categoryList as $category => $dictionaryIdList) {
            foreach ($dictionaryIdList as $dictionaryId) {
                $paramData[] = [
                    "accident_id" => $accidentId,
                    "dictionary_id" => $dictionaryId,
                    "category" => $category,
                    "content" => "",
                    "content_two" => "",
                    "score" => 0,
                    "update_time" => $time,
                ];
            }
        }
        Yii::$app->db->createCommand()->batchInsert(AccidentCasesScore::tableName(), $param, $paramData)->execute();
        //初始化评价维度
        AccidentCasesDimensionService::initContent($accidentId, self::getContentDictionaryIdList(self::getCategoryList()));
    }

    public static function getQuery()
    {
        return AccidentCasesScore::find()->where(["delete_time" => 0]);
    }

    public static function checkNeedCalculate(AccidentCasesScore $AccidentCasesScore): bool
    {
        if (in_array($AccidentCasesScore->category, self::getAutoCategoryList())) {
            $need = false;
        } else {
            $need = true;
        }
        return $need;
    }

    /**
     * @return array        [
     * self::$totalScore,
     * self::$EmergencyResponseTotalCategory,
     * self::$OperationalAdjustmentsTotalCategory
     * ];
     */
    protected static function getAutoCategoryList(): array
    {
        return [
            self::$totalScore,
            self::$EmergencyResponseTotalCategory,
            self::$OperationalAdjustmentsTotalCategory
        ];
    }

    public static $quanzhongConfig = [
        247 => 100, //category 2
        248 => 100, //category 3
        249 => 100, //category 3
        250 => 100, //category 3
        251 => 100, //category 3
        252 => 100, //category 3
        253 => 100, //category 3
        346 => 100, //category 4
        347 => 100, //category 4
        348 => 100, //category 4
    ];

    public static function calculateTotalScore($accident_id): void
    {
        $AccidentCasesScoreConfig = AccidentCasesScoreConfig::findOne(1);
        if (!$AccidentCasesScoreConfig) {
            $AccidentCasesScoreConfig = new AccidentCasesScoreConfig();
            $AccidentCasesScoreConfig->content = json_encode(self::$quanzhongConfig);
            $AccidentCasesScoreConfig->save();
        }
        $quanzhong = json_decode($AccidentCasesScoreConfig->content, true);
        $num = 0;
        $calculateTotalScoreObj = new CalculateTotalScoreObj();
        $needUpdate = [];
        /** @var AccidentCasesScore[] $AccidentScoreList */
        $AccidentScoreList = self::getQuery()->andWhere(["accident_id" => $accident_id])->orderBy("accident_id asc")->all();
        foreach ($AccidentScoreList as $AccidentScore) {
            $obj = self::getAccidentCasesScoreObj($AccidentScore);
            if (in_array($AccidentScore->category, self::getAutoCategoryList())) {
                $needUpdate[] = $obj;
            }
            $attr = "_" . $AccidentScore->dictionary_id;
            $calculateTotalScoreObj->$attr = $obj;
            $num++;
            if ($num == 11) {
                $num = 0;
                $calculateTotalScoreObj->calculate($quanzhong);
            }
        }
        foreach ($needUpdate as $value) {
            Yii::$app->db->createCommand()->update(AccidentCasesScore::tableName(), ['score' => $value->score], ["id" => $value->id])->execute();
        }
    }

    public static function calculateTotalScoreAll()
    {
        $AccidentCasesScoreConfig = AccidentCasesScoreConfig::findOne(1);
        $quanzhong = json_decode($AccidentCasesScoreConfig->content, true);
        $needUpdate = [];
        $AccidentScoreArrayList = [];
        /** @var AccidentCasesScore[] $AccidentScoreList */
        $AccidentScoreList = self::getQuery()->select("id,accident_id,category,dictionary_id,score")->all();
        foreach ($AccidentScoreList as $AccidentScore) {
            $AccidentScoreArrayList[$AccidentScore->accident_id][] = $AccidentScore;
        }
        foreach ($AccidentScoreArrayList as $AccidentScoreArray) {
            $calculateTotalScoreObj = new CalculateTotalScoreObj();
            if (count($AccidentScoreArray) === 11) {
                foreach ($AccidentScoreArray as $AccidentScore) {
                    $obj = self::getAccidentCasesScoreObj($AccidentScore);
                    if (in_array($AccidentScore->category, self::getAutoCategoryList())) {
                        $needUpdate[] = $obj;
                    }
                    $attr = "_" . $AccidentScore->dictionary_id;
                    $calculateTotalScoreObj->$attr = $obj;
                }
                $calculateTotalScoreObj->calculate($quanzhong);
            }
        }
        $needUpdateAccidentCasesScore = [];
        foreach ($needUpdate as $value) {
            $needUpdateAccidentCasesScore[] = [
                "id" => $value->id,
                "score" => $value->score,
            ];
        }
        return $needUpdateAccidentCasesScore;
    }

    /**
     * @param $id
     * @return AccidentCasesScore
     * @throws AjaxException
     */
    public static function getAccidentCasesScoreById($id): AccidentCasesScore
    {
        /** @var  AccidentCasesScore $AccidentCasesScore */
        $AccidentCasesScore = self::getQuery()->andWhere(["id" => $id])->one();
        if (!$AccidentCasesScore) {
            throw new AjaxException("该评价不存在！");
        }
        return $AccidentCasesScore;
    }

    /**
     * 获取详情页评价数据
     * @param AccidentCases $AccidentCases
     * @return array
     */
    public static function getAccidentCasesDetailTotalSore(AccidentCases $AccidentCases): array
    {
        $totalScore = [];
        $emergencyResponseTotalScore = [];
        $operationalAdjustmentsTotalScore = [];
        $emergencyResponseScoreList = [];
        $operationalAdjustmentsScoreList = [];
        $accidentCasesScoreList = self::getList($AccidentCases->id);
        self::listAddDimension($AccidentCases->id, $accidentCasesScoreList);
        foreach ($accidentCasesScoreList as $accidentCasesScore) {
            $obj = self::getAccidentCasesScoreObj($accidentCasesScore);
            if ($obj->category == self::$totalScore) {
                $totalScore = $obj;
            } elseif ($obj->category == self::$EmergencyResponseTotalCategory) {
                $obj->category = 0;
                $emergencyResponseTotalScore = $obj;
            } elseif ($obj->category == self::$OperationalAdjustmentsTotalCategory) {
                $obj->category = 0;
                $operationalAdjustmentsTotalScore = $obj;
            } elseif ($obj->category == self::$EmergencyResponseCategory) {
                $obj->category = 0;
                $emergencyResponseScoreList[] = $obj;
            } elseif ($obj->category == self::$OperationalAdjustmentsCategory) {
                $obj->category = 0;
                $operationalAdjustmentsScoreList[] = $obj;
            }
        }
        return [$totalScore, $emergencyResponseTotalScore, $operationalAdjustmentsTotalScore, $emergencyResponseScoreList, $operationalAdjustmentsScoreList];
    }

    /**
     * 案件总评分列表
     * @param $accidentIds
     * @return array|ActiveRecord[]
     */
    public static function getTotalScoreList($accidentIds)
    {
        return self::getList($accidentIds, [self::$totalScore]);
    }

    public static function getEmergencyResponseScore($accidentId): array
    {
        return self::getScore($accidentId, [self::$EmergencyResponseTotalCategory, self::$EmergencyResponseCategory]);
    }

    public static function getOperationalAdjustmentsScore($accidentId): array
    {
        return self::getScore($accidentId, [self::$OperationalAdjustmentsTotalCategory, self::$OperationalAdjustmentsCategory]);
    }

    public static function updateByTotalScore($accidentId, $totalScore)
    {
        $param = [
            "content" => "",
            "content_two" => "",
        ];
        if ($totalScore) {
            if (isset($totalScore["content"])) {
                $param["content"] = $totalScore["content"];
            }
            if (isset($totalScore["content_two"])) {
                $param["content_two"] = $totalScore["content_two"];
            }
        }
        self::updateByAccidentId($accidentId, $param);
    }

    /**
     * @throws \Throwable
     * @throws AjaxException
     */
    public static function updateById($id, $allParams, $userInfo)
    {
        $model = self::getAccidentCasesScoreById($id);
//        $origin = AdminLogService::getOrigin($model, $allParams);
        self::update($model, $allParams, $userInfo);
//        AdminLogService::saveLogWithUpdateHistory($origin, $model, $allParams);
    }


    /**
     * @param $accidentId
     * @param $allParams
     * @return void
     * @throws AjaxException
     * @throws \Throwable
     */
    public
    static function updateByAccidentId($accidentId, $allParams)
    {
        /** @var  AccidentCasesScore $model */
        $model = self::getQuery()->andWhere(["accident_id" => $accidentId, "category" => self::$totalScore])->one();
        if (!$model) {
            throw new AjaxException("总分不存在！");
        }
        self::update($model, $allParams);
    }

    public
    static function deleteByAccidentCasesId($accident_id): void
    {
        AccidentCasesScore::updateAll(["delete_time" => time()], ["accident_id" => $accident_id]);
    }

    /**
     * @param AccidentCasesScore $model
     * @param $allParams
     * @param $userInfo
     * @return void
     * @throws AjaxException
     * @throws \Throwable
     */
    protected static function update(AccidentCasesScore $model, $allParams, $userInfo)
    {
        $origin = AdminLogService::getOrigin($model, $allParams);
        $case = CaseService::checkIsPublish($model->accident_id, $userInfo);
        if (!isset($allParams["score"]) && !isset($allParams["content"]) && !isset($allParams["content_two"])) {
            return;
        }
        $needCalculate = self::checkNeedCalculate($model);
        if ($needCalculate) {
            $model->score = $allParams["score"];
        }
        $model->content = $allParams["content"] ?? "";
        $model->content_two = $allParams["content_two"] ?? "";
        $model->update_time = time();
        //开启事务
        Yii::$app->db->transaction(function () use ($model, $needCalculate) {
            if (!$model->save()) {
                throw new Exception($model->getErrorSummary(true)[0]);
            }
            //计算总分
            if ($needCalculate) {
                self::calculateTotalScore($model->accident_id);
            }
        });
        AdminLogService::saveLogWithUpdateHistory($origin, $model, $case->id, $case->title, $allParams);
    }

    protected
    static function getScore($accidentId, $categoryList): array
    {
        $AccidentCasesScoreList = self::getList($accidentId, $categoryList);
        self::listAddDimension($accidentId, $AccidentCasesScoreList);
        $scoreList = [];
        $totalScore = [];
        foreach ($AccidentCasesScoreList as $AccidentCasesScore) {
            $scoreObj = self::getAccidentCasesScoreObj($AccidentCasesScore);
            if ($scoreObj->category === $categoryList[0]) {
                $scoreObj->category = 0;
                $totalScore = $scoreObj;
            } else {
                $scoreObj->category = 0;
                $scoreList[] = $scoreObj;
            }
        }
        return [$scoreList, $totalScore];
    }

    protected
    static function listAddDimension($accidentId, $data): void
    {
        $newAccidentCasesDimensionList = [];
        $AccidentCasesDimensionList = AccidentCasesDimensionService::getList($accidentId);
        foreach ($AccidentCasesDimensionList as $AccidentCasesDimension) {
            $newAccidentCasesDimensionList[$AccidentCasesDimension->dictionary_id][] = new AccidentCasesDimensionObj($AccidentCasesDimension);
        }
        foreach ($data as $value) {
            $value->dimension = $newAccidentCasesDimensionList[$value->dictionary_id] ?? [];
        }
    }

    /**
     * @param AccidentCasesScore $AccidentCasesScore
     * @return AccidentCasesScoreObj
     */
    protected
    static function getAccidentCasesScoreObj(AccidentCasesScore $AccidentCasesScore): AccidentCasesScoreObj
    {
        return new AccidentCasesScoreObj($AccidentCasesScore);
    }

    /**
     *
     * @param $accidentId
     * @param array $categoryList
     * @return AccidentCasesScore[]
     */
    public
    static function getList($accidentId, array $categoryList = []): array
    {
        /** @var AccidentCasesScore[] $AccidentCasesScoreList */
        $query = self::getQuery()->andWhere(["accident_id" => $accidentId]);
        if ($categoryList != []) {
            $query->andWhere(["category" => $categoryList]);
        }
        $AccidentCasesScoreList = $query->select("id,accident_id,dictionary_id,category,content,content_two,score")
            ->All();
//        if (!$AccidentCasesScoreList) {
//            self::initScore($accidentId);
//            return self::getList($accidentId, $categoryList);
//        }
        return $AccidentCasesScoreList;
    }
}