<?php

declare(strict_types=1);

namespace app\common\model\exam;

use app\common\model\account\Department;
use app\common\model\account\User as UserModel;
use app\common\model\core\Excel;
use app\control\model\User;
use mb\helper\Collection;
use think\facade\Db;
use app\common\model\Base;
use Exception;
use think\facade\Log;

/**
 * Class Subject
 * @package app\common\model\exam
 */
class Subject
{
    /**
     * title
     * @param array $filter
     * @param int $pIndex
     * @param int $pSize
     * @param int $total
     * @return array
     */
    public static function search(array $filter, int $pIndex = 1, int $pSize = 10, &$total = 0)
    {
        $where = [];
        if (!empty($filter['title'])) {
            $where[] = ['title', 'like', "%{$filter['title']}%"];
        }
        if (!empty($filter['timeCreatedMax'])) {
            $where[] = ['time_created', '<=', strtotime($filter['timeCreatedMax'])];
        }
        if (!empty($filter['timeCreatedMin'])) {
            $where[] = ['time_created', '>=', strtotime($filter['timeCreatedMin'])];
        }
        if (!empty($filter['ids'])) {
            $where[] = ['id', 'in', "{$filter['ids']}"];
        }
        try {
            $total = Db::table('exam_subjects')
                ->where($where)->count();
            $query = Db::table('exam_subjects')
                ->where($where);
            if (!empty($pIndex)) {
                $query->page($pIndex, $pSize);
            }
            $dataSet = $query->select()->toArray();
            if (!empty($dataSet)) {
                return $dataSet;
            } else {
                return [];
            }
        } catch (Exception $e) {
            Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR);
        }
        return [];
    }

    /**
     * title
     * watch
     * @param string $type
     * @param array $data
     * @return bool|int|string
     */
    public static function add(string $type, array $data)
    {
        $newData = [];
        if ($type == 'single') {
            $newData['title'] = $data['title'];
            $newData['watch'] = '';
            try {
                $id = Db::table('exam_subjects')
                    ->insertGetId($newData);
                Db::table('exam_subject_watch')->insert(['subject_id' => $id, 'type' => '', 'binding_id' => 0]);
                return $id;
            } catch (Exception $e) {
            }
        } else {
            $newData = array_map(
                function ($val) {
                    return ['title' => $val, 'watch' => ''];
                },
                $data['title']
            );
            try {
                array_map(
                    function ($e) {
                        $id = Db::table('exam_subjects')->insertGetId($e);
                        Db::table('exam_subject_watch')->insert(['subject_id' => $id, 'type' => '', 'binding_id' => 0]);
                    },
                    $newData
                );
                return true;
            } catch (Exception $e) {
                Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR);
            }
        }
        return false;
    }

    /**
     * @param array $where
     * @param array $data
     * @return bool
     */
    public static function update(array $where, array $data)
    {
        try {
            $offect = Db::table('exam_subjects')
                ->where($where)
                ->update($data);
            if ($offect === 1) {
                return true;
            }
            return false;
        } catch (Exception $e) {
            Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR);
        }
        return false;
    }

    /**
     * @param array $titles
     * @param int $id
     * @return bool
     */
    public static function check(array $titles, int $id = 0)
    {
        try {
            foreach ($titles as $val) {
                $res = Db::table('exam_subjects')
                    ->where(['title' => $val])->find();
                if ((empty($id) && !empty($res)) || (!empty($id) && !empty($res) && ($res['id'] != $id))) {
                    return false;
                    break;
                }
            }
            return true;
        } catch (Exception $e) {
            Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR);
        }
        return false;
    }

    /**
     * @param array $where
     * @param array $data
     * @return bool
     */
    public static function watch(array $where, array $data)
    {
        $arr = [
            'paramId' => $where['id'],
            'department' => $data['department'],
            'user' => $data['user']
        ];
        try {
            $res = Base::watch('subject', $arr);
            if (!$res) {
                return false;
            }
            Db::table('exam_subjects')->where(['id' => $where['id']])->update(
                [
                    'watch' => serialize(
                        [
                            'department' => $data['department'],
                            'user' => $data['user']
                        ]
                    )
                ]
            );
            return true;
        } catch (Exception $e) {
            Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR);
        }
        return false;
    }

    /**
     * @param string $type
     * @param string $ids
     * @return bool
     */
    public static function delete(string $type, string $ids)
    {
        if ($type == 'single') {
            $where[] = ['id', '=', $ids];
            $watchWhere[] = ['subject_id', '=', $ids];
        } else {
            $where[] = ['id', 'in', "{$ids}"];
            $watchWhere[] = ['subject_id', 'in', "{$ids}"];
        }
        try {
            $offset = Db::table('exam_subjects')
                ->where($where)
                ->delete();
            if ($offset) {
                Db::table('exam_subject_watch')->where($watchWhere)->delete();
                Db::table('exam_knowledge')->where($watchWhere)->delete();
                return true;
            }
            return false;
        } catch (Exception $e) {
            Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR);
        }
        return false;
    }

    /**
     * @return array
     */
    public static function userWatch()
    {
        try {
            $user = User::fetchCurrent();
            $subjectIds = Db::table('exam_subject_watch')->where(
                "`type` = '' or (`type` = 'department' and `binding_id` = {$user['department']}) 
            or (`type` = 'user' and `binding_id` = {$user['id']})"
            )->group('subject_id')->field('subject_id')->select()->toArray();
            return Base::neaten($subjectIds, 'subject_id');
        } catch (Exception $e) {
            Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR);
        }
        return [];
    }

    /**
     * @param $id
     * @return array
     */
    public static function fetch($id)
    {
        $where = [];
        if (is_array($id)) {
            if (!empty($id['title'])) {
                $where[] = ['title', '=', $id['title']];
            }
        } else {
            $where[] = ['id', '=', $id];
        }
        try {
            $userInfo = Db::table('exam_subjects')
                ->where($where)
                ->find();
            if (!empty($userInfo)) {
                return Collection::keyStyle($userInfo, Collection::NAME_STYLE_JAVA);
            }
        } catch (Exception $e) {
            Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR);
        }
        return [];
    }

    public static function import($src)
    {
        $subjects = Excel::read(
            $src,
            [
                ['field' => 'subject', 'column' => 'A'],
                ['field' => 'knowledge', 'column' => 'B'],
            ]
        );
        if (empty($subjects) || is_error($subjects)) {
            return error(-24, '文件错误,未读取到数据');
        }
        $line = 1;
        $error = [];
        foreach ($subjects as $v) {
            $line++;
            $params = [];
            $paramsKnowledge = [];
            if (empty($v['subject'])) {
                $error[] = ['line' => $line, 'msg' => '科目名称为空'];
                continue;
            }
            $exists = self::fetch(['title' => $v['subject']]);
            if (!empty($exists)) {
                if (empty($v['knowledge'])) {
                    $error[] = ['line' => $line, 'msg' => '科目名称存在'];
                    continue;
                }
                $existsKnowledge = Knowledge::fetch(['title' => $v['knowledge']]);
                if (!empty($existsKnowledge)) {
                    $error[] = ['line' => $line, 'msg' => '知识点已存在'];
                    continue;
                }
                $paramsKnowledge['subjectId'] = $exists['id'];
                $paramsKnowledge['title'] = $v['knowledge'];
            } else {
                $params['title'] = $v['subject'];
                $subjectId = self::add('single', $params);
                if (is_error($subjectId)) {
                    $error[] = ['line' => $line, 'msg' => '科目添加失败'];
                    continue;
                }
                if (!empty($v['knowledge'])) {
                    $paramsKnowledge['subjectId'] = $subjectId;
                    $paramsKnowledge['title'] = $v['knowledge'];
                }
            }
            $res = Knowledge::add($paramsKnowledge);
            if (is_error($res)) {
                $error[] = ['line' => $line, 'msg' => '知识点添加失败'];
                continue;
            }
        }
        return $error;
    }
}