package com.xjrsoft.module.student.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.common.enums.DeleteMark;
import com.xjrsoft.common.enums.GenderDictionaryEnum;
import com.xjrsoft.common.exception.MyException;
import com.xjrsoft.common.model.result.R;
import com.xjrsoft.common.model.result.RT;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.FileZipUtil;
import com.xjrsoft.common.utils.TreeUtil;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.base.entity.BaseClass;
import com.xjrsoft.module.base.entity.BaseGrade;
import com.xjrsoft.module.base.service.IBaseClassService;
import com.xjrsoft.module.base.service.IBaseGradeService;
import com.xjrsoft.module.concat.service.IXjrUserService;
import com.xjrsoft.module.hikvision.util.DataUtil;
import com.xjrsoft.module.organization.entity.UserDeptRelation;
import com.xjrsoft.module.organization.service.IUserDeptRelationService;
import com.xjrsoft.module.room.service.IRoomBedService;
import com.xjrsoft.module.student.dto.AddBaseStudentUserDto;
import com.xjrsoft.module.student.dto.BaseStudentUserPageDto;
import com.xjrsoft.module.student.dto.UpdateBaseStudentUserDto;
import com.xjrsoft.module.student.entity.BaseStudent;
import com.xjrsoft.module.student.entity.BaseStudentUser;
import com.xjrsoft.module.student.service.IStudentManagerService;
import com.xjrsoft.module.student.vo.BaseDepMajorGradeClassStudenTreeVo;
import com.xjrsoft.module.student.vo.BaseStudentSchoolRollVo;
import com.xjrsoft.module.student.vo.BaseStudentTreeVo;
import com.xjrsoft.module.student.vo.BaseStudentUserPageVo;
import com.xjrsoft.module.student.vo.BaseStudentUserVo;
import com.xjrsoft.module.teacher.entity.XjrUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

@RestController
@RequestMapping("/student" + "/studentmanager")
@Api(value = "/student" + "/studentmanager", tags = "学生基本信息管理代码")
@AllArgsConstructor
public class StudentManagerController {

    private final IStudentManagerService studentManagerService;
    private final IBaseGradeService baseGradeService;
    private final IBaseClassService baseClassService;
    private final IXjrUserService xjrUserService;
    private final IRoomBedService roomBedService;
    private final IUserDeptRelationService userDeptRelationService;
    @GetMapping(value = "/page")
    @ApiOperation(value = "学生列表(分页)")
    @SaCheckPermission("studentmanager:detail")
    public R page(@Valid BaseStudentUserPageDto dto) {
        if(dto.getTreeType() != null && dto.getTreeId() != null){
            dto.setQueryId(dto.getTreeId());
            if(dto.getTreeType() == 3){
                String[] split = dto.getTreeId().split("_");
                dto.setTreeId(split[0]);
                dto.setQueryId(split[1]);
            }
        }

        IPage<BaseStudentUserPageVo> page = studentManagerService.getStudentPage(new Page<>(dto.getLimit(), dto.getSize()), dto);
        for (BaseStudentUserPageVo record : page.getRecords()) {
            BaseStudentUser user = studentManagerService.getById(record.getId());
            record.setAvatar(user.getAvatar());
        }
        PageOutput<BaseStudentUserPageVo> pageOutput = ConventPage.getPageOutput(page, BaseStudentUserPageVo.class);
        return R.ok(pageOutput);
    }

    @GetMapping(value = "/tree")
    @ApiOperation(value = "学生年纪班级树")
    @SaCheckPermission("studentmanager:detail")
    public RT<List<BaseStudentTreeVo>> tree() {
        List<String> roleList = StpUtil.getRoleList();

        long teacherId = StpUtil.getLoginIdAsLong();
        List<BaseClass> classList = baseClassService.list(
            new QueryWrapper<BaseClass>().lambda().eq(BaseClass::getDeleteMark, DeleteMark.NODELETE.getCode())
        );
        List<BaseStudentTreeVo> voList = new ArrayList<>();

        List<BaseGrade> gradeList = baseGradeService.list(
            new QueryWrapper<BaseGrade>().lambda().eq(BaseGrade::getDeleteMark, DeleteMark.NODELETE.getCode())
        );
        if(roleList.size() == 2 && roleList.contains("CLASSTE") && roleList.contains("TEACHER")){
            Set<Long> gradeSet = new HashSet<>();
            for (BaseClass baseClass : classList) {
                if(baseClass.getTeacherId().equals(teacherId)){
                    gradeSet.add(baseClass.getGradeId());
                    voList.add(new BaseStudentTreeVo(){{
                        setId(baseClass.getId());
                        setName(baseClass.getName());
                        setParentId(baseClass.getGradeId());
                    }});
                }
            }
            gradeList.forEach((node) -> {
                if(gradeSet.contains(node.getId())){
                    voList.add(new BaseStudentTreeVo(){{
                        setId(node.getId());
                        setName(node.getName());
                    }});
                }
            });

            List<BaseStudentTreeVo> treeVoList = TreeUtil.build(voList);

            return RT.ok(treeVoList);
        }
        gradeList.forEach((node) -> {
            voList.add(new BaseStudentTreeVo(){{
                setId(node.getId());
                setName(node.getName());
            }});
        });

        classList.forEach((node)->{
            voList.add(new BaseStudentTreeVo(){{
                setId(node.getId());
                setName(node.getName());
                setParentId(node.getGradeId());
            }});
        });

        List<BaseStudentTreeVo> treeVoList = TreeUtil.build(voList);

        return RT.ok(treeVoList);
    }

    @GetMapping(value = "/info")
    @ApiOperation(value = "根据id查询学生信息")
    @SaCheckPermission("studentmanager:detail")
    public R info(@RequestParam Long id) {
        BaseStudentUser baseStudentUser = studentManagerService.getByIdDeep(id);
        if (baseStudentUser == null) {
            return R.error("找不到此数据！");
        }
        BaseStudentUserVo userVo = BeanUtil.toBean(baseStudentUser, BaseStudentUserVo.class);

        for (BaseStudentSchoolRollVo roll : userVo.getBaseStudentSchoolRollList()) {
            BaseClass aClass = baseClassService.getById(roll.getClassId());
            XjrUser xjrUser = xjrUserService.getById(aClass.getTeacherId());
            if(xjrUser != null){
                roll.setTeacherName(xjrUser.getName());
            }


            String roomName = roomBedService.getRoomNameByStudentUserId(roll.getUserId());
            roll.setRoomName(roomName);
        }

        List<Long> deptIds = userDeptRelationService.list(Wrappers.lambdaQuery(UserDeptRelation.class)
                        .eq(UserDeptRelation::getUserId, userVo.getId()))
                .stream().map(UserDeptRelation::getDeptId).collect(Collectors.toList());
        String allDeptIdStr = StrUtil.join(StringPool.COMMA, deptIds);
        userVo.setDepartmentIds(allDeptIdStr);

        userVo.setGenderCn(GenderDictionaryEnum.getValue(userVo.getGender()));

        return R.ok(userVo);
    }

    @GetMapping(value = "/major-grade-class-tree")
    @ApiOperation(value = "学生部门专业年级班级树")
    @SaCheckPermission("studentmanager:detail")
    public RT<List<BaseDepMajorGradeClassStudenTreeVo>> tree2() {
        return RT.ok(studentManagerService.deptMajorGradeClassTree());
    }


    @PostMapping
    @ApiOperation(value = "新增学生")
    @SaCheckPermission("studentmanager:add")
    public R add(@Valid @RequestBody AddBaseStudentUserDto dto){
        return R.ok(studentManagerService.add(dto));
    }

    @PostMapping("upload-image")
    @ApiOperation(value = "上传学生学籍照片")
    @SaCheckPermission("studentmanager:add")
    public R uploadImage(@RequestParam("file") MultipartFile file, @Valid @RequestParam Long userId) throws IOException {
        return R.ok(studentManagerService.uploadImage(userId, file));
    }

    @PutMapping
    @ApiOperation(value = "修改学生")
    @SaCheckPermission("studentmanager:edit")
    public R update(@Valid @RequestBody UpdateBaseStudentUserDto dto){
        return R.ok(studentManagerService.update(dto));
    }

    @DeleteMapping
    @ApiOperation(value = "删除")
    @SaCheckPermission("studentmanager:delete")
    public R delete(@Valid @RequestBody List<Long> ids) {
        //删除海康的用户信息
        DataUtil dataUtil = new DataUtil();
        dataUtil.deletePerson(ids);
        return R.ok(studentManagerService.delete(ids));
    }

    @GetMapping(value = "/class")
    @ApiOperation(value = "获取当前学生的班主任")
    public R studentClass() {
        Long userId = StpUtil.getLoginIdAsLong();
        return R.ok(studentManagerService.getStudentClass(userId));
    }


    @PostMapping("/import")
    @ApiOperation(value = "导入学生信息")
    public RT<Boolean> importData(@RequestParam("file") MultipartFile file) throws IOException, ParseException {
        List<Map<Integer, Object>> excelDataList = EasyExcel.read(file.getInputStream()).sheet().headRowNumber(3).doReadSync();

        return RT.ok(studentManagerService.importStudentData(excelDataList));
    }


    @PostMapping(value = "/avatar-import")
    @ApiOperation(value = "批量导入学生学学籍照")
    @SaCheckPermission("stundentfaceprocess:batch-upload")
    public RT<Boolean> batchUpload(@RequestParam("file") MultipartFile file) throws Exception {
        List<BaseStudentUser> list = studentManagerService.list(
                new MPJLambdaWrapper<BaseStudentUser>().distinct()
                        .select(BaseStudentUser::getId)
                        .select(BaseStudentUser.class, x -> VoToColumnUtil.fieldsToColumns(BaseStudentUser.class).contains(x.getProperty()))
                        .leftJoin(BaseStudent.class, BaseStudent::getUserId, BaseStudentUser::getId)
                        .eq(BaseStudent::getDeleteMark, DeleteMark.NODELETE.getCode())
                        .eq(BaseStudentUser::getDeleteMark, DeleteMark.NODELETE.getCode())
        );
        Map<String, BaseStudentUser> studentMap = new HashMap<>();
        for (BaseStudentUser baseStudentUser : list) {
            studentMap.put(baseStudentUser.getCredentialNumber(), baseStudentUser);
        }

        ZipFile zipFile = FileZipUtil.convertToZipFile(file);
        Enumeration<? extends ZipEntry> entries = zipFile.entries();


        Map<String, String> map = new HashMap<String, String>() {
            {
                put("jpg", "data:image/jpg;base64,");
                put("jpeg", "data:image/jpeg;base64,");
                put("png", "data:image/png;base64,");
            }
        };
        String[] imgSuffix = new String[]{"png", "jpg", "jpeg"};
        while (entries.hasMoreElements()){
            ZipEntry entry = entries.nextElement();
            String filename = entry.getName();
            InputStream inputStream = zipFile.getInputStream(entry); //读取文件内容
            String[] split = filename.split("\\.");
            String idNumber = split[0].substring(split[0].length() - 18);
            String suffix = StringUtils.substringAfterLast(filename, StringPool.DOT);


            BaseStudentUser studentUser = studentMap.get(idNumber);
            if(studentUser == null){
                continue;
            }
            if (!Arrays.asList(imgSuffix).contains(suffix)) {
                throw new MyException("图片格式不正确！");
            }
            //将照片转换成base64
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            byte[] imageBytes = outputStream.toByteArray();
            String base64String = map.get(suffix) + Base64.getEncoder().encodeToString(imageBytes);
            inputStream.close();
            outputStream.close();

            studentUser.setAvatar(base64String);

            studentManagerService.updateById(studentUser);

        }
        return RT.ok(true);
    }
}
