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.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.common.enums.StudentCadreLevelEnum;
import com.xjrsoft.common.model.result.RT;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.base.entity.BaseClass;
import com.xjrsoft.module.base.mapper.BaseClassMapper;
import com.xjrsoft.module.student.dto.AddBaseStudentCadreDto;
import com.xjrsoft.module.student.dto.BaseStudentCadrePageDto;
import com.xjrsoft.module.student.dto.UpdateBaseStudentCadreDto;
import com.xjrsoft.module.student.entity.BaseStudent;
import com.xjrsoft.module.student.entity.BaseStudentCadre;
import com.xjrsoft.module.student.entity.BaseStudentPost;
import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
import com.xjrsoft.module.student.mapper.BaseStudentSchoolRollMapper;
import com.xjrsoft.module.student.service.IBaseStudentCadreService;
import com.xjrsoft.module.student.vo.BaseStudentCadrePageVo;
import com.xjrsoft.module.student.vo.BaseStudentCadreVo;
import com.xjrsoft.module.teacher.entity.XjrUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
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 javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
* @title: 学生干部管理
* @Author dzx
* @Date: 2023-11-14
* @Version 1.0
*/
@RestController
@RequestMapping("/student" + "/basestudentcadre")
@Api(value = "/student"  + "/basestudentcadre",tags = "学生干部管理代码")
@AllArgsConstructor
public class BaseStudentCadreController {


    private final IBaseStudentCadreService baseStudentCadreService;
    private final BaseStudentSchoolRollMapper baseStudentSchoolRollMapper;
    private final BaseClassMapper baseClassMapper;

    @GetMapping(value = "/classlist")
    @ApiOperation(value="获取班主任管理的班级")
    @SaCheckPermission("basestudentcadre:detail")
    public RT<List<BaseClass>> classList(){
        List<BaseClass> pageOutput = baseClassMapper.selectJoinList(BaseClass.class, new MPJLambdaWrapper<BaseClass>()
                .disableSubLogicDel()
                .eq(BaseClass::getTeacherId, StpUtil.getLoginIdAsLong())
        );

        return RT.ok(pageOutput);
    }

    @GetMapping(value = "/mobliepage")
    @ApiOperation(value="学生干部管理列表(移动端分页)")
    @SaCheckPermission("basestudentcadre:detail")
    public RT<PageOutput<BaseStudentCadrePageVo>> mobliepage(@Valid BaseStudentCadrePageDto dto){
        // 如果未传班级id和职务id，
        if(!StrUtil.equals(dto.getLevel(), StudentCadreLevelEnum.CLASS.getCode()) && ObjectUtil.isEmpty(dto.getPostId())){
            PageOutput<BaseStudentCadrePageVo> result = ConventPage.getPageOutputNull(BaseStudentCadrePageVo.class);
            return RT.ok(result);
        }

        IPage<BaseStudentCadrePageVo> page = baseStudentCadreService.selectJoinListPage(ConventPage.getPage(dto), BaseStudentCadrePageVo.class,
                MPJWrappers.<BaseStudentCadre>lambdaJoin()
                .like(StrUtil.isNotBlank(dto.getUserName()), XjrUser::getName, dto.getUserName())
                .eq(ObjectUtil.isNotEmpty(dto.getClassId()), BaseStudentCadre::getClassId, dto.getClassId())
                .eq(ObjectUtil.isNotEmpty(dto.getPostId()), BaseStudentCadre::getPostId, dto.getPostId())
                .eq(ObjectUtil.isNotEmpty(dto.getLevel()), BaseStudentPost::getLevel, dto.getLevel())
                .eq(ObjectUtil.isNotEmpty(dto.getPost()), BaseStudentPost::getPost, dto.getPost())
                .eq(StrUtil.equals(dto.getLevel(), StudentCadreLevelEnum.CLASS.getCode()), BaseClass::getTeacherId, StpUtil.getLoginIdAsLong())
                .between(ObjectUtil.isNotNull(dto.getStartTimeStart()) && ObjectUtil.isNotNull(dto.getStartTimeEnd()), BaseStudentCadre::getStartTime,dto.getStartTimeStart(),dto.getStartTimeEnd())
                .between(ObjectUtil.isNotNull(dto.getEndTimeStart()) && ObjectUtil.isNotNull(dto.getEndTimeEnd()), BaseStudentCadre::getEndTime,dto.getEndTimeStart(),dto.getEndTimeEnd())
                .orderByDesc(BaseStudentCadre::getId)
                .selectAs(BaseStudent::getStudentId, BaseStudentCadrePageVo::getStudentId)
                .selectAs(XjrUser::getName, BaseStudentCadrePageVo::getUserName)
                .selectAs(BaseClass::getName, BaseStudentCadrePageVo::getClassName)
                .selectAs(BaseStudentPost::getPost, BaseStudentCadrePageVo::getPost)
                .selectAs(BaseStudentPost::getLevel, BaseStudentCadrePageVo::getLevel)
                .select(BaseStudentCadre::getId)
                .select(BaseStudentCadre.class,x -> VoToColumnUtil.fieldsToColumns(BaseStudentCadrePageVo.class).contains(x.getProperty()))
                .innerJoin(XjrUser.class, XjrUser::getId, BaseStudentCadre::getUserId)
                .innerJoin(BaseStudent.class, BaseStudent::getUserId, BaseStudentCadre::getUserId)
                .innerJoin(BaseStudentPost.class, BaseStudentPost::getId, BaseStudentCadre::getPostId)
                .leftJoin(BaseClass.class, BaseClass::getId, BaseStudentCadre::getClassId)
                .leftJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, BaseStudentCadre::getUserId)).setSize(15);

        PageOutput<BaseStudentCadrePageVo> pageOutput = ConventPage.getPageOutput(page, BaseStudentCadrePageVo.class);
        return RT.ok(pageOutput);
    }


    @GetMapping(value = "/page")
    @ApiOperation(value="学生干部管理列表(分页)")
    @SaCheckPermission("basestudentcadre:detail")
    public RT<PageOutput<BaseStudentCadrePageVo>> page(@Valid BaseStudentCadrePageDto dto){

        IPage<BaseStudentCadrePageVo> page = baseStudentCadreService.getListPage(dto);

        PageOutput<BaseStudentCadrePageVo> pageOutput = ConventPage.getPageOutput(page, BaseStudentCadrePageVo.class);
        return RT.ok(pageOutput);
    }

    @GetMapping(value = "/info")
    @ApiOperation(value="根据id查询学生干部管理信息")
    @SaCheckPermission("basestudentcadre:detail")
    public RT<BaseStudentCadreVo> info(@RequestParam Long id){

        BaseStudentCadreVo baseStudentCadreVo = baseStudentCadreService.getOneById(id);
        if (baseStudentCadreVo == null) {
           return RT.error("找不到此数据！");
        }
        return RT.ok(baseStudentCadreVo);
    }


    @PostMapping
    @ApiOperation(value = "新增学生干部管理（批量新增）")
    @SaCheckPermission("basestudentcadre:add")
    public RT<Boolean> add(@Valid @RequestBody List<AddBaseStudentCadreDto> dto){
        //循环判定，是否已经存在于数据库，并查询出班级id
        List<AddBaseStudentCadreDto> addDtoList = new ArrayList<>();
        for (AddBaseStudentCadreDto baseStudentCadreDto : dto) {
            List<BaseStudentCadre> list = baseStudentCadreService.list(
                    Wrappers.lambdaQuery(BaseStudentCadre.class)
                            .eq(BaseStudentCadre::getUserId, baseStudentCadreDto.getUserId())
                            .eq(BaseStudentCadre::getPostId, baseStudentCadreDto.getPostId())
            );
            if(ObjectUtil.isNotNull(list) && list.size() == 1){
                continue;
            }

            BaseStudentSchoolRoll baseStudentSchoolRoll = baseStudentSchoolRollMapper.selectOne(Wrappers.lambdaQuery(BaseStudentSchoolRoll.class).eq(BaseStudentSchoolRoll::getUserId, baseStudentCadreDto.getUserId()));
            if(ObjectUtil.isNotNull(baseStudentSchoolRoll)){
                baseStudentCadreDto.setClassId(baseStudentSchoolRoll.getClassId());
            }
            addDtoList.add(baseStudentCadreDto);
        }
        List<BaseStudentCadre> baseStudentCadreList = BeanUtil.copyToList(addDtoList, BaseStudentCadre.class);
        boolean isSuccess = baseStudentCadreService.addAll(baseStudentCadreList);
        return RT.ok(isSuccess);
    }

    @PostMapping("/addone")
    @ApiOperation(value = "新增学生干部管理(单个添加)")
    @SaCheckPermission("basestudentcadre:insert")
    public RT<Boolean> addOne(@Valid @RequestBody AddBaseStudentCadreDto dto){
        //判定，是否已经存在于数据库，并查询出班级id
        BaseStudentCadre one = baseStudentCadreService.getOne(
                Wrappers.lambdaQuery(BaseStudentCadre.class)
                .eq(BaseStudentCadre::getUserId, dto.getUserId())
                .eq(BaseStudentCadre::getPostId, dto.getPostId())
        );
        if(ObjectUtil.isNotNull(one)){
            return RT.error("该学生已有该职务，无法重复添加");
        }

        BaseStudentSchoolRoll baseStudentSchoolRoll = baseStudentSchoolRollMapper.selectOne(Wrappers.lambdaQuery(BaseStudentSchoolRoll.class).eq(BaseStudentSchoolRoll::getUserId, dto.getUserId()));
        if(ObjectUtil.isNotNull(baseStudentSchoolRoll)){
            dto.setClassId(baseStudentSchoolRoll.getClassId());
        }

        BaseStudentCadre baseStudentCadre = BeanUtil.toBean(dto, BaseStudentCadre.class);
        boolean isSuccess = baseStudentCadreService.addOne(baseStudentCadre);
        return RT.ok(isSuccess);
    }

    @PutMapping("/editStatus")
    @ApiOperation(value = "修改学生干部状态（离职、复职）")
    @SaCheckPermission("basestudentcadre:edit")
    public RT<Boolean> editStatus(@Valid @RequestBody UpdateBaseStudentCadreDto dto){
        if(ObjectUtil.isNull(dto) || ObjectUtil.isNull(dto.getId()) || ObjectUtil.isNull(dto.getStatus()) ||
                (dto.getStatus() != null && dto.getStatus() == 1 && ObjectUtil.isNull(dto.getLeaveTime()))){
            String msg = "请传入id、status";
            if(dto.getStatus() != null && dto.getStatus() == 1 && ObjectUtil.isNull(dto.getLeaveTime())){
                msg = "请传入id、status和leaveTime";
            }
            return RT.error(msg);
        }

        BaseStudentCadre baseStudentCadre = BeanUtil.toBean(dto, BaseStudentCadre.class);
        return RT.ok(baseStudentCadreService.updateById(baseStudentCadre));
    }

    @PutMapping("/mobile-editStatus")
    @ApiOperation(value = "修改学生干部状态（离职、复职）移动端")
    @SaCheckPermission("basestudentcadre:edit")
    public RT<Boolean> editMobileStatus(@Valid @RequestBody UpdateBaseStudentCadreDto dto){
        if(ObjectUtil.isNull(dto) || ObjectUtil.isNull(dto.getId()) || ObjectUtil.isNull(dto.getStatus())){
            String msg = "请传入id、status";
            return RT.error(msg);
        }

        //（1:在职 0:离职）
        if(dto.getStatus() == 0 && ObjectUtil.isNull(dto.getLeaveTime())){
            String msg = "数据错误";
            return RT.error(msg);
        }

        if(dto.getStatus() == 1 && (ObjectUtil.isNull(dto.getStartTime()) || ObjectUtil.isNull(dto.getEndTime()))){
            String msg = "数据错误";
            return RT.error(msg);
        }

        return RT.ok(baseStudentCadreService.editMobileStatus(dto));
    }

    @PutMapping
    @ApiOperation(value = "修改学生干部管理")
    @SaCheckPermission("basestudentcadre:edit")
    public RT<Boolean> update(@Valid @RequestBody UpdateBaseStudentCadreDto dto){

        BaseStudentCadre baseStudentCadre = BeanUtil.toBean(dto, BaseStudentCadre.class);
        return RT.ok(baseStudentCadreService.updateById(baseStudentCadre));

    }

    @DeleteMapping
    @ApiOperation(value = "删除学生干部管理")
    @SaCheckPermission("basestudentcadre:delete")
    public RT<Boolean> delete(@Valid @RequestBody List<Long> ids){
        return RT.ok(baseStudentCadreService.removeBatchByIds(ids));

    }

    @GetMapping("/export")
    @ApiOperation(value = "导出")
    public ResponseEntity<byte[]> exportData(@Valid BaseStudentCadrePageDto dto, @RequestParam(defaultValue = "false") Boolean isTemplate) {
        List<BaseStudentCadrePageVo> customerList = isTemplate != null && isTemplate ? new ArrayList<>() : ((PageOutput<BaseStudentCadrePageVo>) page(dto).getData()).getList();
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, BaseStudentCadrePageVo.class).automaticMergeHead(false).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(customerList);

        return RT.fileStream(bot.toByteArray(), "BaseStudentCadre" + ExcelTypeEnum.XLSX.getValue());
    }
}