package com.qmth.exam.reserve.controller.admin;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.qmth.boot.api.annotation.Aac;
import com.qmth.boot.api.constant.ApiConstant;
import com.qmth.boot.core.collection.PageResult;
import com.qmth.boot.core.exception.StatusException;
import com.qmth.boot.tools.excel.ExcelWriter;
import com.qmth.boot.tools.excel.enums.ExcelType;
import com.qmth.exam.reserve.bean.login.LoginUser;
import com.qmth.exam.reserve.bean.stdapply.*;
import com.qmth.exam.reserve.controller.BaseController;
import com.qmth.exam.reserve.enums.Role;
import com.qmth.exam.reserve.service.ApplyTaskService;
import com.qmth.exam.reserve.service.CategoryService;
import com.qmth.exam.reserve.service.ExamSiteService;
import com.qmth.exam.reserve.service.StudentApplyService;
import com.qmth.exam.reserve.util.ResourceUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Api(tags = "【管理端】考生预约明细相关接口")
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/admin/apply")
@Aac(strict = false, auth = true)
public class StudentApplyController extends BaseController {

    @Autowired
    private StudentApplyService studentApplyService;

    @Autowired
    private ApplyTaskService applyTaskService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private ExamSiteService examSiteService;


    @ApiOperation(value = "预约任务列表")
    @PostMapping(value = "/task/list")
    public List<CategoryVO> listTask() {
        return applyTaskService.listTask();
    }

    @ApiOperation(value = "教学点列表")
    @PostMapping(value = "/teaching/list")
    public List<CategoryVO> listTeaching(@ApiParam("查询启用的教学点或查询所有的教学点") @RequestParam(required = false) Boolean flag) {
        LoginUser user = this.curLoginUser();
        return categoryService.listTeaching(user, flag);
    }

    @ApiOperation(value = "考点列表")
    @PostMapping(value = "/agent/list")
    public List<CategoryVO> listAgent(@ApiParam("教学点ID") @RequestParam Long id,
                                      @ApiParam("查询启用的考点或查询所有的考点") @RequestParam(required = false) Boolean flag) {
        return examSiteService.listExamSite(id, flag);
    }

    @ApiOperation(value = "考生预约名单详情分页")
    @PostMapping(value = "/std/page")
    public PageResult<StudentApplyVO> page(@RequestBody StudentApplyReq req) {
        LoginUser user = this.curLoginUser();
        if (user.getRole().equals(Role.TEACHING)) {
            req.setTeachingId(user.getCategoryId());
        }
        return studentApplyService.page(req);
    }

    @ApiOperation(value = "取消预约")
    @PostMapping(value = "/std/cancel")
    public void cancel(@ApiParam("预约结果ID") @RequestParam Long id) {
        LoginUser user = this.curLoginUser();
        studentApplyService.cancel(user, id);
    }

    @ApiOperation(value = "导入预考模版下载")
    @PostMapping(value = "/imp/template")
    public void download(HttpServletResponse response) {
        exportFile("导入预考模板.xlsx", ResourceUtil.getStream("templates/preExamImport.xlsx"));
    }

    @ApiOperation(value = "导入预考")
    @PostMapping(value = "/import")
    public Map<String, Object> importPreExamStd(@ApiParam("教学点ID") @RequestParam(required = false) Long teachingId,
            @ApiParam("教学点所在的层级") @RequestParam(required = false) Integer level, @RequestParam MultipartFile file) {
        LoginUser user = this.curLoginUser();
        if (Role.TEACHING.equals(user.getRole())) {
            teachingId = user.getCategoryId();
        }
        List<Map<String, Object>> failRecords = new ArrayList<>();
        try {
            failRecords = studentApplyService.importPreExam(user, teachingId, level, file.getInputStream());
        } catch (IOException e) {
            throw new StatusException("文件读取出错", e);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("hasError", CollectionUtils.isNotEmpty(failRecords));
        map.put("failRecords", failRecords);
        return map;
    }

    @ApiOperation(value = "一键自动分配")
    @PostMapping(value = "/std/auto/assign")
    public String autoAssign(@ApiParam("任务ID") @RequestParam Long taskId) {
        if (taskId == null) {
            throw new StatusException("请选择预约任务");
        }
        LoginUser user = this.curLoginUser();
        if (!Role.ADMIN.equals(user.getRole())) {
            throw new StatusException("没有权限");
        }
        studentApplyService.autoAssign(taskId, user.getId());
        return "后台正在执行中，请耐心等待！";
    }

    @ApiOperation(value = "打印签到表")
    @PostMapping(value = "/std/auto/sign/in/print")
    public void printSignIn(@ApiParam("教学点ID") @RequestParam(required = false) Long teachingId,
            @ApiParam("考点ID") @RequestParam(required = false) Long agentId,
            @ApiParam("考试日期") @RequestParam(required = true) Long examDate) {
        LoginUser user = this.curLoginUser();
        if (Role.ADMIN.equals(user.getRole()) && teachingId == null) {
            throw new StatusException("请选择教学点");
        }
        if (Role.TEACHING.equals(user.getRole())) {
            teachingId = user.getCategoryId();
        }
        File signInZip = studentApplyService.downloadSignIn(teachingId, agentId, examDate);
        exportFile(signInZip.getName(), signInZip);
        signInZip.delete();
    }

    @Aac(strict = false, auth = false)
    @ApiOperation(value = "自动排考")
    @PostMapping(value = "/std/auto/layout")
    public void autoLayout(@ApiParam("教学点ID") @RequestParam(required = false) Long teachingId) {
        // LoginUser user = this.curLoginUser();
        // if (!Role.ADMIN.equals(user.getRole())) {
        // throw new StatusException("没有权限");
        // }
        studentApplyService.autoLayout(teachingId);
    }

    @ApiOperation(value = "可打印签到表的日期")
    @PostMapping(value = "/sign/in/date")
    public List<SignInVO> listSignInDate(@ApiParam("预约任务ID") @RequestParam(required = false) Long taskId) {
        return studentApplyService.listSignInDate(taskId);
    }


    @ApiOperation(value = "导出考场预约情况表")
    @PostMapping(value = "/export/teaching/available")
    public void exportApplyAvailable(@ApiParam("教学点ID") @RequestParam Long teachingId, HttpServletResponse response) {
        try {
            String fileName = URLEncoder.encode("考点预约情况表", "UTF-8");
            response.setHeader("Content-Disposition", "inline; filename=" + fileName + ".xlsx");
            response.setContentType("application/vnd.ms-excel");
            ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX);
            List<CategoryVO> examSiteList = examSiteService.listExamSite(teachingId, Boolean.TRUE);
            if(examSiteList == null || examSiteList.isEmpty()) {
                throw new StatusException("当前教学点下没有考点");
            }
            String[] columnNames = getColumnNames(examSiteList);
            String[] firstLineContents = getFirstLineContents(examSiteList);
            List<String[]> exportList = new ArrayList<>();
            exportList.add(firstLineContents);
            List<String[]> avaiableList = studentApplyService.listExamSiteAvailable(examSiteList);
            exportList.addAll(avaiableList);
            writer.writeDataArrays("考点预约情况表", null, columnNames, exportList.iterator());
            writer.output(response.getOutputStream());
        } catch (IOException e) {
            throw new StatusException(e.getMessage());
        }
    }

    private String[] getFirstLineContents(List<CategoryVO> examSiteList) {
        String[] result = new String[examSiteList.size()+1];
        result[0] = "考点容量";
        for (int i = 0; i < examSiteList.size(); i++) {
            CategoryVO category = examSiteList.get(i);
            result[i+1] = String.valueOf(category.getCapacity());
        }
        return result;
    }

    private String[] getColumnNames(List<CategoryVO> examSiteList) {
        String[] columnNames = new String[examSiteList.size()+1];
        columnNames[0] = "时段";
        for (int i = 0; i < examSiteList.size(); i++) {
            CategoryVO category = examSiteList.get(i);
            columnNames[i+1] = category.getName();
        }
        return columnNames;
    }

    @ApiOperation(value = "导出考生预约的详情信息")
    @PostMapping(value = "/export/std/detail")
    public void exportHaveApplyStudent(@ApiParam("教学点ID") @RequestParam Long teachingId, HttpServletResponse response) {
        try {
            String fileName = URLEncoder.encode("考生预约详情信息表", "UTF-8");
            response.setHeader("Content-Disposition", "inline; filename=" + fileName + ".xlsx");
            response.setContentType("application/vnd.ms-excel");
            ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX);
            List<StudentApplyExport> applyList = studentApplyService.listStudentApplyExport(teachingId);
            if(CollectionUtils.isEmpty(applyList)) {
                throw new StatusException("教学点下还没有考生预约");
            }
            writer.writeObjects("考生预约详情", null, StudentApplyExport.class, applyList.iterator());
            writer.output(response.getOutputStream());
        } catch (IOException e) {
            throw new StatusException(e.getMessage());
        }
    }

    @ApiOperation(value = "导出未预约的考生")
    @GetMapping(value = "/export/std/noApply")
    public void exportNoApplyStudent(@ApiParam("教学点ID") @RequestParam Long teachingId, HttpServletResponse response) {
        try {
            String fileName = URLEncoder.encode("未完成预约考生信息表", "UTF-8");
            response.setHeader("Content-Disposition", "inline; filename=" + fileName + ".xlsx");
            response.setContentType("application/vnd.ms-excel");
            ExcelWriter writer = ExcelWriter.create(ExcelType.XLSX);
            List<StudentExport> studentList = studentApplyService.listStudentNoApply(teachingId);
            if(CollectionUtils.isEmpty(studentList)) {
                throw new StatusException("该教学点下的考生已全部完成预约");
            }
            writer.writeObjects("未完成预约考生", null, StudentExport.class, studentList.iterator());
            writer.output(response.getOutputStream());
        } catch (IOException e) {
            throw new StatusException(e.getMessage());
        }
    }

}
