package com.xjrsoft.module.student.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.enums.EnabledMark;
import com.xjrsoft.common.model.result.RT;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.config.CommonPropertiesConfig;
import com.xjrsoft.module.base.entity.BaseUserStudent;
import com.xjrsoft.module.base.entity.WhitelistManagement;
import com.xjrsoft.module.base.service.IBaseUserStudentService;
import com.xjrsoft.module.base.service.IWhitelistManagementService;
import com.xjrsoft.module.organization.entity.User;
import com.xjrsoft.module.organization.entity.UserRoleRelation;
import com.xjrsoft.module.organization.service.IUserRoleRelationService;
import com.xjrsoft.module.organization.service.IUserService;
import com.xjrsoft.module.student.dto.ActiveAccountDto;
import com.xjrsoft.module.student.dto.AddBaseNewStudentDto;
import com.xjrsoft.module.student.dto.BaseNewStudentPageDto;
import com.xjrsoft.module.student.dto.UpdateBaseNewStudentDto;
import com.xjrsoft.module.student.entity.BaseNewStudent;
import com.xjrsoft.module.student.entity.BaseStudentFamilyMember;
import com.xjrsoft.module.student.service.IBaseNewStudentService;
import com.xjrsoft.module.student.service.IBaseStudentFamilyMemberService;
import com.xjrsoft.module.student.vo.BaseNewStudentPageVo;
import com.xjrsoft.module.student.vo.BaseNewStudentScoreExcelVo;
import com.xjrsoft.module.student.vo.BaseNewStudentTreeVo;
import com.xjrsoft.module.student.vo.BaseNewStudentVo;
import com.xjrsoft.module.student.vo.EnrollmentPlanGradeVo;
import com.xjrsoft.module.student.vo.EnrollmentPlanTreeVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
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.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
* @title: 新生维护信息
* @Author dzx
* @Date: 2024-06-27
* @Version 1.0
*/
@RestController
@RequestMapping("/student" + "/baseNewStudent")
@Api(value = "/student"  + "/baseNewStudent",tags = "新生维护信息代码")
@AllArgsConstructor
public class BaseNewStudentController {

    private final IUserService userService;
    private final IBaseNewStudentService baseNewStudentService;
    private final IBaseStudentFamilyMemberService familyMemberService;
    private final IWhitelistManagementService whitelistManagementService;
    private final IUserRoleRelationService userRoleRelationService;
    private final RedisUtil redisUtil;
    private final IBaseUserStudentService userStudentService;
    private final CommonPropertiesConfig propertiesConfig;
    @GetMapping(value = "/page")
    @ApiOperation(value="新生维护信息列表(分页)")
    @SaCheckPermission("basenewstudent:detail")
    public RT<PageOutput<BaseNewStudentPageVo>> page(@Valid BaseNewStudentPageDto dto){

        Page<BaseNewStudentPageVo> page = baseNewStudentService.getPage(new Page<>(dto.getLimit(), dto.getSize()), dto);
        PageOutput<BaseNewStudentPageVo> pageOutput = ConventPage.getPageOutput(page, BaseNewStudentPageVo.class);
        return RT.ok(pageOutput);
    }

    @GetMapping(value = "/tree")
    @ApiOperation(value="新生维护信息树")
    @SaCheckPermission("basenewstudent:detail")
    public RT<List<BaseNewStudentTreeVo>> tree(){

        List<EnrollmentPlanGradeVo> gradeList = baseNewStudentService.getGradeList();
        List<EnrollmentPlanTreeVo> list = baseNewStudentService.getEnrollmentPlanList();

        List<BaseNewStudentTreeVo> result = new ArrayList<>();
        for (EnrollmentPlanGradeVo gradeVo : gradeList) {
            BaseNewStudentTreeVo treeVo = new BaseNewStudentTreeVo() {{
                setId(gradeVo.getId());
                setName(gradeVo.getName());
                setTreeType(1);
            }};
            List<BaseNewStudentTreeVo> children = new ArrayList<>();
            for (EnrollmentPlanTreeVo planTreeVo : list) {
                if(planTreeVo.getGradeId().equals(gradeVo.getId())){
                    children.add(new BaseNewStudentTreeVo() {{
                        setId(planTreeVo.getId());
                        setName(planTreeVo.getEnrollTypeCn());
                        setTreeType(2);
                    }});
                }
            }

            treeVo.setChildren(children);
            result.add(treeVo);
        }

        return RT.ok(result);
    }

    @GetMapping(value = "/info")
    @ApiOperation(value="根据id查询新生维护信息信息")
    @SaCheckPermission("basenewstudent:detail")
    public RT<BaseNewStudentVo> info(@RequestParam Long id){
        BaseNewStudent baseNewStudent = baseNewStudentService.getById(id);
        if (baseNewStudent == null) {
           return RT.error("找不到此数据！");
        }
        return RT.ok(BeanUtil.toBean(baseNewStudent, BaseNewStudentVo.class));
    }


    @PostMapping
    @ApiOperation(value = "新增新生维护信息")
    @SaCheckPermission("basenewstudent:add")
    public RT<Boolean> add(@Valid @RequestBody AddBaseNewStudentDto dto){
        BaseNewStudent baseNewStudent = BeanUtil.toBean(dto, BaseNewStudent.class);
        baseNewStudent.setFirstAmbitionId(Long.parseLong(dto.getFirstAmbition()));
        baseNewStudent.setSecondAmbitionId(Long.parseLong(dto.getSecondAmbition()));
        baseNewStudent.setCreateDate(new Date());
        boolean isSuccess = baseNewStudentService.save(baseNewStudent);
        return RT.ok(isSuccess);
    }

    @PutMapping
    @ApiOperation(value = "修改新生维护信息")
    @SaCheckPermission("basenewstudent:edit")
    public RT<Boolean> update(@Valid @RequestBody UpdateBaseNewStudentDto dto){

        BaseNewStudent baseNewStudent = BeanUtil.toBean(dto, BaseNewStudent.class);
        return RT.ok(baseNewStudentService.updateById(baseNewStudent));

    }

    @DeleteMapping
    @ApiOperation(value = "删除新生维护信息")
    @SaCheckPermission("basenewstudent:delete")
    public RT<Boolean> delete(@Valid @RequestBody List<Long> ids){
        return RT.ok(baseNewStudentService.removeBatchByIds(ids));

    }
    @PostMapping("/import")
    @ApiOperation(value = "导入")
    public RT<List<Map<String, String>>> importData(@RequestParam Long treeId, @RequestParam MultipartFile file) throws IOException {
        List<Map<Integer, Object>> errorList = baseNewStudentService.importData(treeId, file);
        List<Map<String, String>> result = new ArrayList<>();

        for (Map<Integer, Object> objectMap : errorList) {
            Map<String, String> object = new LinkedHashMap<>();
            object.put("毕业学校", objectMap.get(0)==null?"":objectMap.get(0).toString());
            object.put("学生姓名", objectMap.get(1)==null?"":objectMap.get(1).toString());
            object.put("性别", objectMap.get(2)==null?"":objectMap.get(2).toString());
            object.put("身份证号", objectMap.get(3)==null?"":objectMap.get(3).toString());
            object.put("身高(cm)", objectMap.get(4)==null?"":objectMap.get(4).toString());
            object.put("体重（kg）", objectMap.get(5)==null?"":objectMap.get(5).toString());
            object.put("毕业班级", objectMap.get(6)==null?"":objectMap.get(6).toString());
            object.put("学生来源", objectMap.get(7)==null?"":objectMap.get(7).toString());
            object.put("住宿类型", objectMap.get(8)==null?"":objectMap.get(8).toString());
            object.put("手机号", objectMap.get(9)==null?"":objectMap.get(9).toString());
            object.put("第一志愿", objectMap.get(10)==null?"":objectMap.get(10).toString());
            object.put("第二志愿", objectMap.get(11)==null?"":objectMap.get(11).toString());
            object.put("是否可调配", objectMap.get(12)==null?"":objectMap.get(12).toString());
            object.put("家庭电话", objectMap.get(13)==null?"":objectMap.get(13).toString());
            object.put("家庭地址", objectMap.get(14)==null?"":objectMap.get(14).toString());
            object.put("错误信息", objectMap.get(15)==null?"":objectMap.get(15).toString());
            result.add(object);
        }
        return RT.ok(result);
    }

    @PostMapping("/score-import")
    @ApiOperation(value = "成绩导入")
    public RT<List<Map<String, String>>> scoreImport(@RequestParam MultipartFile file) throws IOException {
        List<BaseNewStudentScoreExcelVo> errorList = baseNewStudentService.scoreImport(file);
        List<Map<String, String>> result = new ArrayList<>();

        for (BaseNewStudentScoreExcelVo objectMap : errorList) {
            Map<String, String> object = new LinkedHashMap<>();
            object.put("毕业学校", objectMap.getGraduateSchool());
            object.put("姓名", objectMap.getName());
            object.put("性别", objectMap.getGender());
            object.put("班级", objectMap.getGraduateClass());
            object.put("总成绩", objectMap.getScore().intValue() + "");
            object.put("错误信息", "未能查询到该学生或该学生存在多个");
            result.add(object);
        }
        return RT.ok(result);
    }

    @PostMapping("/active-account")
    @ApiOperation(value = "激活账号")
    public RT<Boolean> activeAccount(@Valid @RequestBody ActiveAccountDto dto) {
        User user = userService.getById(dto.getId());
        user.setMobile(dto.getMobile());
        user.setEnabledMark(EnabledMark.ENABLED.getCode());
        user.setModifyDate(LocalDateTime.now());
        userService.updateById(user);
        // 新增家庭成员信息
        List<BaseStudentFamilyMember> list = familyMemberService.list(
                new QueryWrapper<BaseStudentFamilyMember>().lambda()
                        .eq(BaseStudentFamilyMember::getName, dto.getParentName())
                        .eq(BaseStudentFamilyMember::getUserId, dto.getId())
                        .eq(BaseStudentFamilyMember::getMobile, dto.getParentMobile())
        );
        BaseStudentFamilyMember member;
        if(list.isEmpty()){
            member = new BaseStudentFamilyMember();
            member.setUserId(user.getId());
            member.setName(dto.getParentName());
            member.setMobile(dto.getParentMobile());
            member.setCreateDate(LocalDateTime.now());
            member.setCreateUserId(StpUtil.getLoginIdAsLong());
            familyMemberService.save(member);
        }else{
            member = list.get(0);
        }
        List<User> parents = userService.list(
                new QueryWrapper<User>().lambda()
                        .eq(User::getUserName, dto.getParentMobile())
                        .or()
                        .eq(User::getMobile, dto.getParentMobile())
        );
        if(parents.isEmpty()){
            User parentUser = new User() {{
                setUserName(dto.getParentMobile());
                setName(dto.getParentName());
                setIsChangePassword(1);
                setDeleteMark(0);
                setEnabledMark(1);
                setPassword(BCrypt.hashpw(propertiesConfig.getDefaultPassword(), BCrypt.gensalt()));
                setMobile(dto.getParentMobile());
            }};
            userService.save(parentUser);

            userRoleRelationService.save(new UserRoleRelation(){{
                setUserId(parentUser.getId());
                setRoleId(4L);
            }});

            BaseUserStudent userStudent = new BaseUserStudent();
            userStudent.setStudentId(user.getId());
            userStudent.setStudentNane(user.getName());
            userStudent.setStudentIdentity(user.getCredentialNumber());
            userStudent.setCreateDate(new Date());
            userStudent.setUserId(parentUser.getId());
            userStudent.setStatus(1);
            userStudentService.save(userStudent);
        }else{
            User parentUser = parents.get(0);
            BaseUserStudent userStudent = new BaseUserStudent();
            userStudent.setStudentId(user.getId());
            userStudent.setStudentNane(user.getName());
            userStudent.setStudentIdentity(user.getCredentialNumber());
            userStudent.setCreateDate(new Date());
            userStudent.setUserId(parentUser.getId());
            userStudent.setStatus(1);
            userStudentService.save(userStudent);
        }

        //新增白名单信息
        List<WhitelistManagement> managementList = whitelistManagementService.list(
                new QueryWrapper<WhitelistManagement>().lambda()
                        .eq(WhitelistManagement::getUserId, dto.getId())
        );
        if(managementList.isEmpty()){
            WhitelistManagement whitelistManagement = new WhitelistManagement() {{
                setName(user.getName());
                setUserId(user.getId());
                setCreateDate(new Date());
                setCredentialNumber(user.getCredentialNumber());
                setPhone(user.getMobile());
            }};
            whitelistManagementService.save(whitelistManagement);
        }

        CompletableFuture.runAsync(() -> {
            List<User> userList = userService.list();
            redisUtil.set(GlobalConstant.USER_CACHE_KEY, userList);

            List<UserRoleRelation> userRoleRelationList = userRoleRelationService.list(Wrappers.lambdaQuery(UserRoleRelation.class));
            redisUtil.set(GlobalConstant.USER_ROLE_RELATION_CACHE_KEY, userRoleRelationList);

            whitelistManagementService.loadCaches();
        });

        return RT.ok(true);
    }

}