package com.ym.mec.web.controller;

import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.StudentPaymentOrderDao;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.CourseViewTypeEnum;
import com.ym.mec.biz.dal.enums.PaymentStatusEnum;
import com.ym.mec.biz.dal.page.*;
import com.ym.mec.biz.service.EmployeeService;

import com.ym.mec.common.exception.BizException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.ym.mec.biz.dal.dao.MusicGroupDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderCourseSettingsDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderDao;
import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
import com.ym.mec.biz.service.MusicGroupSubjectPlanService;
import com.ym.mec.biz.service.StudentPreRegistrationService;
import com.ym.mec.biz.service.StudentRegistrationService;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.entity.HttpResponseResult;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import com.ym.mec.util.excel.POIUtil;

@RequestMapping("studentRegistration")
@Api(tags = "学生报名信息服务")
@RestController
public class StudentRegistrationController extends BaseController {

    @Autowired
    private StudentRegistrationService studentRegistrationService;
    @Autowired
    private MusicGroupSubjectPlanService musicGroupSubjectPlanService;
    @Autowired
    private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
    @Autowired
    private MusicGroupPaymentCalenderCourseSettingsDao musicGroupPaymentCalenderCourseSettingsDao;
    @Autowired
    private StudentPreRegistrationService studentPreRegistrationService;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;

    @ApiOperation(value = "乐团预报名列表分页查询")
    @GetMapping("/queryPreApplyList")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/queryPreApplyList')")
    public Object queryPreApplyList(StudentPreRegistrationQueryInfo queryInfo) {
        return succeed(studentPreRegistrationService.queryListForPage(queryInfo));
    }

    @ApiOperation(value = "乐团预报名声部列表查询")
    @GetMapping("/queryPreApplySubjectList")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/queryPreApplySubjectList')")
    public Object queryPreApplySubjectList(String musicGroupId) {
        return succeed(studentPreRegistrationService.querySubjectNum(musicGroupId));
    }

    @ApiOperation(value = "乐团添加学员")
    @PostMapping("/insertStudent")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/insertStudent')")
    public Object add(@RequestBody StudentAddDto studentAddDto) throws Exception {
        return succeed(studentRegistrationService.insertStudent(studentAddDto));
    }

    @ApiOperation(value = "修改学生报名信息")
    @PostMapping("/update")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/update')")
    public Object update(StudentRegistration studentRegistration) {
        studentRegistration.setUpdateTime(new Date());
        studentRegistrationService.update(studentRegistration);
        return succeed();
    }

    @ApiOperation(value = "调剂学生报名专业")
    @PostMapping("/batchUpdateSubject")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/batchUpdateSubject')")
    @ApiImplicitParams({@ApiImplicitParam(name = "userId", value = "学生编号", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "subId", value = "声部编号", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "Integer")})
    public Object batchUpdateSubject(Integer userId, Integer subId, String musicGroupId) throws Exception {
        if (null == userId || subId == null || StringUtils.isEmpty(musicGroupId)) {
            return failed("参数校验异常");
        }
        return succeed(studentRegistrationService.batchUpdateSubject(userId, subId, musicGroupId));
    }

    @ApiOperation(value = "乐团【报名中、缴费中】 学生详情列表分页查询")
    @GetMapping("/queryStudentApplyDetail")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/queryStudentApplyDetail')")
    public Object queryStudentApplyDetail(StudentRegistrationQueryInfo queryInfo) {
        return succeed(studentRegistrationService.queryStudentDetailPage(queryInfo));
    }

    @ApiOperation(value = "学生报名缴费金额详情")
    @GetMapping("/queryFeeDetail")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/queryFeeDetail')")
    @ApiImplicitParams({@ApiImplicitParam(name = "studentId", value = "学生编号", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String")})
    public Object queryFeeDetail(String studentId, String musicGroupId) {
        if (StringUtils.isEmpty(studentId) || StringUtils.isEmpty(musicGroupId)) {
            return failed("参数校验异常");
        }
        return succeed(studentRegistrationService.queryFeeDetail(Integer.parseInt(studentId), musicGroupId));
    }

    @ApiOperation(value = "获取未分班的学生")
    @GetMapping("/getNoClassStu")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getNoClassStu')")
    @ApiImplicitParams({@ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "actualSubjectId", value = "科目(声部)id,多个逗号分开", required = true, dataType = "String")})
    public Object getNoClassStuBySubjectId(String musicGroupId, String actualSubjectId) {
        return succeed(studentRegistrationService.getNoClassStuBySubjectId(musicGroupId, actualSubjectId));
    }

    @ApiOperation(value = "获取班级学生")
    @GetMapping("/getClassStu")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getClassStu')")
    @ApiImplicitParams({@ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "classGroupId", value = "班级id", required = true, dataType = "int")})
    public Object getClassStu(String musicGroupId, int classGroupId) {
        return succeed(studentRegistrationService.findClassGroupStu(musicGroupId, classGroupId));
    }

    @ApiOperation(value = "获取乐团(声部)的学生")
    @GetMapping("/getMusicGroupStu")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getMusicGroupStu')")
    @ApiImplicitParams({@ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "actualSubjectId", value = "科目(声部)id,", required = false, dataType = "String")})
    public HttpResponseResult getMusicGroupStu(String musicGroupId, String actualSubjectId) {
        return succeed(studentRegistrationService.findMusicGroupStudent(musicGroupId, actualSubjectId));
    }

    @ApiOperation(value = "获取乐团未分班的学生")
    @GetMapping("/getMusicGroupNoClassStu")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getMusicGroupNoClassStu')")
    @ApiImplicitParams({@ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "actualSubjectId", value = "科目(声部)id,", required = false, dataType = "int")})
    public HttpResponseResult getMusicGroupNoClassStu(String musicGroupId, Integer actualSubjectId) {
        return succeed(studentRegistrationService.findMusicGroupNoClassGroupStudent(musicGroupId, actualSubjectId));
    }

    @ApiOperation(value = "开启缴费(单独学生)")
    @PostMapping("/openPayment")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/openPayment')")
    @ApiImplicitParams({@ApiImplicitParam(name = "ids", value = "报名id（不是userId）,逗号分隔", required = true, dataType = "String")})
    public HttpResponseResult openPayment(String ids) throws IOException {
        return succeed(studentRegistrationService.openPayment(ids));
    }

    @ApiOperation(value = "获取乐团(声部)的(没有某种班级类型)学生")
    @GetMapping("/getMusicGroupStuNoClassType")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getMusicGroupStuNoClassType')")
    @ApiImplicitParams({@ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String"),
            @ApiImplicitParam(name = "type", value = "类型(MIX，HIGH)", required = true, dataType = "ClassGroupTypeEnum"),
            @ApiImplicitParam(name = "actualSubjectId", value = "科目(声部)id,", required = false, dataType = "String")})
    public HttpResponseResult getMusicGroupStuNoClassType(String musicGroupId, Long classGroupId, ClassGroupTypeEnum type, String actualSubjectId) {
        return succeed(studentRegistrationService.findMusicGroupStuNoClassType(musicGroupId, classGroupId, type, actualSubjectId));
    }

    @ApiOperation(value = "获取学生报名缴费详情")
    @GetMapping("/getApplyDetail")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getApplyDetail')")
    @ApiImplicitParams({@ApiImplicitParam(name = "studentId", value = "学生编号", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String")})
    public HttpResponseResult<List<StudentPaymentOrderDetail>> getApplyDetail(Integer studentId, String musicGroupId) {
        if (studentId == null || StringUtils.isEmpty(musicGroupId)) {
            return failed("参数校验异常");
        }
        return succeed(studentRegistrationService.getStudentApplyDetail(studentId, musicGroupId));
    }

    @ApiOperation(value = "获取乐团声部费用信息及乐器和辅件")
    @GetMapping("/getSubjectGoodsAndInfo")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getSubjectGoodsAndInfo')")
    @ApiImplicitParams({@ApiImplicitParam(name = "subjectId", value = "声部信息", required = true, dataType = "Integer"),
            @ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String")})
    public HttpResponseResult<MusicGroupSubjectGoodsAndInfoDto> getSubjectGoodsAndInfo(Integer subjectId, String musicGroupId, Long calenderId) {
        if (subjectId == null || StringUtils.isEmpty(musicGroupId) || calenderId == null) {
            return failed("参数校验异常");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        MusicGroupSubjectGoodsAndInfoDto subjectGoodsAndInfo = musicGroupSubjectPlanService.getSubjectGoodsAndInfo(musicGroupId, subjectId);

        MusicGroupPaymentCalender musicGroupRegCalender = musicGroupPaymentCalenderDao.get(calenderId);
        if (musicGroupRegCalender != null && musicGroupRegCalender.getPayUserType().equals(MusicGroupPaymentCalender.PayUserType.STUDENT)) {
            List<MusicGroupPaymentCalenderCourseSettings> courseSettings = musicGroupPaymentCalenderCourseSettingsDao.getWithPaymentCalender(musicGroupRegCalender.getId());
            musicGroupRegCalender.setMusicGroupPaymentCalenderCourseSettingsList(courseSettings);
            subjectGoodsAndInfo.setMusicGroupPaymentCalender(musicGroupRegCalender);
        }
        subjectGoodsAndInfo.setMusicGroup(musicGroup);
        return succeed(subjectGoodsAndInfo);
    }

    @ApiOperation(value = "获取班级课程的价值")
    @GetMapping("/getClassGroupCourseExpectPrice")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getClassGroupCourseExpectPrice')")
    public Object getClassGroupCourseExpect(List<Integer> classGroupIds) {
        return succeed(studentRegistrationService.getClassGroupCourseExpectPrice(classGroupIds));
    }

    @ApiOperation(value = "删除报名的学生")
    @PostMapping("/del")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/del')")
    public HttpResponseResult<Boolean> del(Long id) {
        StudentRegistration studentRegistration = studentRegistrationService.get(id);
        if (studentRegistration == null) {
            return failed("删除的报名信息不存在");
        }
        return succeed(studentRegistrationService.delReg(id));
    }


    @ApiOperation(value = "批量删除报名的学生")
    @PostMapping("/batchDel")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/batchDel')")
    public HttpResponseResult<Boolean> batchDel(@RequestBody DelRegisterDto delRegisterDto) {
        return succeed(studentRegistrationService.batchDelRegs(delRegisterDto.getMusicGroupId(), delRegisterDto.getUserIds()));
    }


    @ApiOperation(value = "获取乐团学生的退费信息")
    @GetMapping("/getMusicGroupStuReBack")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getMusicGroupStuReBack')")
    @ApiImplicitParams({@ApiImplicitParam(name = "musicGroupId", value = "乐团编号", required = true, dataType = "String")})
    public HttpResponseResult getMusicGroupStuReBack(String musicGroupId) {
        return succeed(studentRegistrationService.getMusicGroupStuReBack(musicGroupId));
    }


    @ApiOperation(value = "预报名导出")
    @GetMapping("/preRegisterExport")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/preRegisterExport')")
    public void queryPreApplyList(StudentPreRegistrationQueryInfo queryInfo, HttpServletResponse response) throws Exception {
        queryInfo.setPage(1);
        queryInfo.setRows(49999);

        PageInfo<StudentPreRegistrationDto> studentPreRegistration = studentPreRegistrationService.queryListForPage(queryInfo);
        if (studentPreRegistration.getTotal() <= 0) {
            response.setStatus(200);
            response.setContentType("Content-Type:application/json;charset=UTF-8");
            response.getOutputStream().write("{\"data\": null, \"code\": 500, \"status\": false, \"msg\": \"没有可导出的记录\"}".getBytes());
            response.flushBuffer();
            return;
        }
        MusicGroup musicGroup = musicGroupDao.get(queryInfo.getMusicGroupId());
        for (StudentPreRegistrationDto row : studentPreRegistration.getRows()) {
            if (row.getKitPurchaseMethod().equals("OWNED")) {
                row.setKitPurchaseMethod("自行准备");
            } else if (row.getKitPurchaseMethod().equals("GROUP")) {
                row.setKitPurchaseMethod("团购");
            }
            if ("OWNED".equals(row.getCloudTeacherMethod())) {
                row.setCloudTeacherMethod("自行准备");
            } else if ("GROUP".equals(row.getCloudTeacherMethod())) {
                row.setCloudTeacherMethod("团购");
            }
            if (row.getSubjectFirst().equals(999)) {
                row.setSubjectFirstName("听从老师安排");
            }
            if (row.getSubjectSecond().equals(999)) {
                row.setSubjectSecondName("听从老师安排");
            }
            row.setCurrentGrade(row.getCurrentGrade() + row.getCurrentClass());
        }
        OutputStream outputStream = response.getOutputStream();
        try {
            HSSFWorkbook workbook = null;
            if (musicGroup.getCourseViewType().equals(CourseViewTypeEnum.MEMBER_FEE)) {
                String[] header = {"学员编号", "学员姓名", "性别", "联系电话", "年级班级", "选报声部1", "选报声部2", "是否服从调剂", "乐器准备方式", "练习系统"};
                String[] body = {"userId", "userName", "gender ? '男' : '女'", "phone", "currentGrade", "subjectFirstName", "subjectSecondName", "isAllowAdjust ? '是' : '否'", "kitPurchaseMethod", "cloudTeacherMethod"};
                workbook = POIUtil.exportExcel(header, body, studentPreRegistration.getRows());
            } else {
                String[] header = {"学员编号", "学员姓名", "性别", "联系电话", "年级班级", "选报声部1", "选报声部2", "是否服从调剂", "乐器准备方式", "练习系统"};
                String[] body = {"userId", "userName", "gender ? '男' : '女'", "phone", "currentGrade", "subjectFirstName", "subjectSecondName", "isAllowAdjust ? '是' : '否'", "kitPurchaseMethod", "cloudTeacherMethod"};
                workbook = POIUtil.exportExcel(header, body, studentPreRegistration.getRows());
            }

            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=pre-register-" + DateUtil.getDate(new Date()) + ".xls");
            response.flushBuffer();
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @ApiOperation(value = "查询乐团中未加入班级学员信息")
    @GetMapping("/queryNoClassMusicStudentInfo")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/queryNoClassMusicStudentInfo')")
    public HttpResponseResult queryNoClassMusicStudentInfo(NoClassMusicStudentQueryInfo queryInfo) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            return failed("用户信息获取失败");
        }
        Employee employee = employeeService.get(sysUser.getId());
        if (StringUtils.isBlank(queryInfo.getOrganIds())) {
            queryInfo.setOrganIds(employee.getOrganIdList());
        } else if (StringUtils.isEmpty(employee.getOrganIdList())) {
            return failed("用户所在分部异常");
        } else {
            List<String> list = Arrays.asList(employee.getOrganIdList().split(","));
            if (!list.containsAll(Arrays.asList(queryInfo.getOrganIds().split(",")))) {
                return failed("非法请求");
            }
        }
        return succeed(studentRegistrationService.queryNoClassMusicStudentInfo(queryInfo));
    }

    @ApiOperation(value = "获取报名/预报名列表")
    @GetMapping("/getRegisterOrPreList")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/getRegisterOrPreList')")
    public HttpResponseResult<PageInfoReg<RegisterDto>> queryStudentApplyDetail(RegistrationOrPreQueryInfo queryInfo) {
        if (StringUtils.isNotBlank(queryInfo.getSearch())) {
            List<BasicUserDto> users = studentPaymentOrderDao.getUsers(queryInfo.getSearch());
            List<Integer> userIds = users.stream().map(BasicUserDto::getUserId).collect(Collectors.toList());
            if (userIds.size() > 0) {
                queryInfo.setUserIds(userIds);
            }
        }
        return succeed(studentRegistrationService.getRegisterOrPreList(queryInfo));
    }

    @ApiOperation(value = "获取报名/预报名列表导出")
    @GetMapping("/registerOrPreListExport")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/registerOrPreListExport')")
    public void registerOrPreListExport(RegistrationOrPreQueryInfo queryInfo, HttpServletResponse response) throws Exception {
        if (StringUtils.isNotBlank(queryInfo.getSearch())) {
            List<BasicUserDto> users = studentPaymentOrderDao.getUsers(queryInfo.getSearch());
            List<Integer> userIds = users.stream().map(BasicUserDto::getUserId).collect(Collectors.toList());
            if (userIds.size() > 0) {
                queryInfo.setUserIds(userIds);
            }
        }
        queryInfo.setPage(1);
        queryInfo.setRows(49999);

        PageInfo<RegisterDto> registerOrPreList = studentRegistrationService.getRegisterOrPreList(queryInfo);
        if (registerOrPreList.getTotal() <= 0) {
            throw new BizException("没有可导出的记录");
        }

        List<RegisterDto> hasSoredPreRegs = registerOrPreList.getRows().stream().filter(e -> e.getPerRegisterTime() != null).sorted(Comparator.comparing(RegisterDto::getPerRegisterTime)).collect(Collectors.toList());
        int i = 1;
        for (RegisterDto hasSoredPreReg : hasSoredPreRegs) {
            hasSoredPreReg.setPerRegSort(i);
            i++;
        }

        i = 1;
        List<RegisterDto> pays = registerOrPreList.getRows().stream().filter(e -> e.getPayTime() != null).sorted(Comparator.comparing(RegisterDto::getPayTime)).collect(Collectors.toList());
        for (RegisterDto pay : pays) {
            pay.setPaySort(i);
            i++;
        }

        OutputStream outputStream = response.getOutputStream();
        HSSFWorkbook workbook = null;
        try {
            String[] header = {"学员编号", "学员姓名", "声部", "预报名时间", "预报名时间差", "预报名排名", "缴费时间", "缴费时间差", "缴费排名"};
            String[] body = {"userId", "studentName", "actualSubjectName", "perRegisterTime", "perRegIntervalStr", "perRegSort", "payTime", "payIntervalStr", "paySort"};
            workbook = POIUtil.exportExcel(header, body, registerOrPreList.getRows());
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=registerOrPer-" + DateUtil.getDate(new Date()) + ".xls");
            response.flushBuffer();
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
            workbook.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    workbook.close();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    @ApiOperation(value = "设置不需要云教练")
    @GetMapping("/setNoneCloudTeacher")
    @PreAuthorize("@pcs.hasPermissions('studentRegistration/setNoneCloudTeacher')")
    public HttpResponseResult<Boolean> setNoneCloudTeacher(Long id) {
        StudentRegistration studentRegistration = studentRegistrationService.get(id);
        //已付费的增加，已缴费人数、和0元付费人数
        if (studentRegistration.getPaymentStatus().equals(PaymentStatusEnum.YES)) {
            return succeed(studentRegistrationService.addPaidNum(id));
        } else {
            return succeed(studentRegistrationService.setNoneCloudTeacher(id));
        }
    }
}
