package com.jpsoft.shinestar.modules.base.controller;

import com.github.pagehelper.Page;
import com.jpsoft.shinestar.config.OSSConfig;
import com.jpsoft.shinestar.modules.base.dto.PersonInfoDTO;
import com.jpsoft.shinestar.modules.base.entity.*;
import com.jpsoft.shinestar.modules.base.service.AlarmConfigService;
import com.jpsoft.shinestar.modules.base.service.CompanyInfoService;
import com.jpsoft.shinestar.modules.common.dto.MessageResult;
import com.jpsoft.shinestar.modules.common.dto.Sort;
import com.jpsoft.shinestar.modules.common.utils.CheckIdCard;
import com.jpsoft.shinestar.modules.common.utils.OSSUtil;
import com.jpsoft.shinestar.modules.common.utils.POIUtils;
import com.jpsoft.shinestar.modules.common.utils.PojoUtils;
import com.jpsoft.shinestar.modules.sys.entity.User;
import com.jpsoft.shinestar.modules.sys.service.UserService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/base/alarmConfig")
public class AlarmConfigController {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private AlarmConfigService alarmConfigService;

    @Autowired
    private UserService userService;

    @Autowired
    private CompanyInfoService companyInfoService;

    @Autowired
    private OSSConfig ossConfig;

    @ApiOperation(value="创建空记录")
    @GetMapping("create")
    public MessageResult<AlarmConfig> create(){
        MessageResult<AlarmConfig> msgResult = new MessageResult<>();

        AlarmConfig alarmConfig = new AlarmConfig();

        alarmConfig.setNeedMeasureTemperature(true);
        alarmConfig.setRealTimeStat(1);

        msgResult.setData(alarmConfig);
        msgResult.setResult(true);

        return msgResult;
    }
    
    @ApiOperation(value="添加信息")
    @PostMapping("add")
    public MessageResult<AlarmConfig> add(@RequestBody AlarmConfig alarmConfig,@RequestAttribute String subject){
        MessageResult<AlarmConfig> msgResult = new MessageResult<>();

        try {
            alarmConfig.setId(UUID.randomUUID().toString());
            alarmConfig.setDelFlag(false);
            alarmConfig.setCreateBy(subject);
            alarmConfig.setCreateTime(new Date());

            if(StringUtils.isNotEmpty(alarmConfig.getWeekdays())){
                String[] weekdays =  alarmConfig.getWeekdays().split(",");
                String sortWeekDays = Arrays.stream(weekdays).sorted(Comparator.naturalOrder()).collect(Collectors.joining(","));
                alarmConfig.setWeekdays(sortWeekDays);
            }

            int affectCount = alarmConfigService.insert(alarmConfig);

            if (affectCount > 0) {
                msgResult.setResult(true);
                msgResult.setData(alarmConfig);
            } else {
                msgResult.setResult(false);
                msgResult.setMessage("数据库添加失败");
            }
        }
        catch(Exception ex){
            logger.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="获取信息")
    @GetMapping("edit/{id}")
    public MessageResult<AlarmConfig> edit(@PathVariable("id") String id){
        MessageResult<AlarmConfig> msgResult = new MessageResult<>();

        try {
            AlarmConfig alarmConfig = alarmConfigService.get(id);

            if (alarmConfig != null) {
                msgResult.setResult(true);
                msgResult.setData(alarmConfig);
            } else {
                msgResult.setResult(false);
                msgResult.setMessage("数据库不存在该记录!");
            }
        }
        catch(Exception ex){
            logger.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="更新用户")
    @PostMapping("update")
    public MessageResult<AlarmConfig> update(@RequestBody AlarmConfig alarmConfig,@RequestAttribute String subject){
        MessageResult<AlarmConfig> msgResult = new MessageResult<>();

        try {
            alarmConfig.setUpdateBy(subject);
            alarmConfig.setUpdateTime(new Date());

            if(StringUtils.isNotEmpty(alarmConfig.getWeekdays())){
                String[] weekdays =  alarmConfig.getWeekdays().split(",");
                String sortWeekDays = Arrays.stream(weekdays).sorted(Comparator.naturalOrder()).collect(Collectors.joining(","));
                alarmConfig.setWeekdays(sortWeekDays);
            }

            int affectCount = alarmConfigService.update(alarmConfig);

            if (affectCount > 0) {
                msgResult.setResult(true);
                msgResult.setData(alarmConfig);
            } else {
                msgResult.setResult(false);
                msgResult.setMessage("数据库更新失败");
            }
        }
        catch(Exception ex){
            logger.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

	@ApiOperation(value="删除")
    @PostMapping("delete/{id}")
    public MessageResult<Integer> delete(@PathVariable("id") String id,@RequestAttribute String subject){
        MessageResult<Integer> msgResult = new MessageResult<>();

        try {
            AlarmConfig alarmConfig = alarmConfigService.get(id);
            alarmConfig.setDelFlag(true);
            alarmConfig.setUpdateBy(subject);
            alarmConfig.setUpdateTime(new Date());

            int affectCount = alarmConfigService.update(alarmConfig);

            if (affectCount > 0) {
                msgResult.setResult(true);
                msgResult.setData(affectCount);
            } else {
                msgResult.setResult(false);
                msgResult.setMessage("删除失败");
            }
        }
        catch(Exception ex){
            logger.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }


    @ApiOperation(value="批量删除")
    @PostMapping("batchDelete")
    public MessageResult<Integer> batchDelete(@RequestBody List<String> idList,@RequestAttribute String subject){
        MessageResult<Integer> msgResult = new MessageResult<>();

        try {
            int affectCount = 0;

            for (String id : idList) {
                AlarmConfig alarmConfig = alarmConfigService.get(id);
                alarmConfig.setDelFlag(true);
                alarmConfig.setUpdateBy(subject);
                alarmConfig.setUpdateTime(new Date());

                affectCount += alarmConfigService.update(alarmConfig);
            }

            if (affectCount > 0) {
                msgResult.setResult(true);
                msgResult.setData(affectCount);
            } else {
                msgResult.setResult(false);
                msgResult.setMessage("删除失败");
            }
        }
        catch(Exception ex){
            logger.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="列表")
    @RequestMapping(value = "pageList",method = RequestMethod.POST)
    public MessageResult<Map> pageList(
            String id,
            @RequestParam(value="companyId",defaultValue="") String companyId,
            @RequestParam(value="pageIndex",defaultValue="1") int pageIndex,
            @RequestParam(value="pageSize",defaultValue="20") int pageSize,
            @RequestAttribute String subject){
        MessageResult<Map> msgResult = new MessageResult<>();

        try {
            //当前用户ID
            System.out.println(subject);

            Map<String, Object> searchParams = new HashMap<>();

            User user = userService.get(subject);
            CompanyInfo companyInfo = companyInfoService.get(user.getCompanyId());

            List<Sort> sortList = new ArrayList<>();
            sortList.add(new Sort("b.level_", "asc"));
            sortList.add(new Sort("b.sort_no", "asc"));
            sortList.add(new Sort("b.name_", "asc"));
            sortList.add(new Sort("a.attendance_type", "asc"));
            sortList.add(new Sort("a.weekdays_", "asc"));
            sortList.add(new Sort("a.start_time", "asc"));

            if (StringUtils.isNotEmpty(companyId)) {
                companyInfo = companyInfoService.get(companyId);
                searchParams.put("companyCode", companyInfo.getCode() + "%");
            } else {
                if (!userService.hasRole(subject, "SYSADMIN")) {
                    searchParams.put("companyCode", companyInfo.getCode() + "%");
                }
            }

            Page<AlarmConfig> page = alarmConfigService.pageSearch(searchParams, pageIndex, pageSize, true, sortList);

            msgResult.setResult(true);
            msgResult.setData(PojoUtils.pageWrapper(page));
        }
        catch(Exception ex){
            logger.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }

    @ApiOperation(value="导出考勤时间设置")
    @RequestMapping(value = "exportXls",method = RequestMethod.POST)
    public MessageResult<String> exportXls(
            String id,
            @RequestParam(value="companyId",defaultValue="") String companyId,
            @RequestParam(value="pageIndex",defaultValue="0") int pageIndex,
            @RequestParam(value="pageSize",defaultValue="100000") int pageSize,
            @RequestAttribute String subject){

        //当前用户ID
        System.out.println(subject);
        MessageResult<String> msgResult = new MessageResult<>();
        try {
            Map<String, Object> searchParams = new HashMap<>();

            User user = userService.get(subject);
            CompanyInfo companyInfo = companyInfoService.get(user.getCompanyId());

            List<Sort> sortList = new ArrayList<>();
            sortList.add(new Sort("b.level_","asc"));
            sortList.add(new Sort("b.sort_no","asc"));
            sortList.add(new Sort("b.name_","asc"));
            sortList.add(new Sort("a.attendance_type","asc"));
            sortList.add(new Sort("a.weekdays_","asc"));
            sortList.add(new Sort("a.start_time","asc"));

            if (StringUtils.isNotEmpty(companyId)) {
                searchParams.put("companyId", companyId);
            } else {
                if (!userService.hasRole(subject, "SYSADMIN")) {
                    searchParams.put("companyCode", companyInfo.getCode() + "%");
                }
            }

            Page<AlarmConfig> page = alarmConfigService.pageSearch(searchParams, pageIndex, pageSize, false, sortList);


            HSSFWorkbook workbook = new HSSFWorkbook();
            HSSFSheet sheet = workbook.createSheet();
            //表头
            HSSFRow rowTitle = sheet.createRow(0);
            HSSFCell cellTitle1 = rowTitle.createCell(0);
            cellTitle1.setCellValue("序号");

            HSSFCell cellTitle2 = rowTitle.createCell(1);
            cellTitle2.setCellValue("单位");
            sheet.setColumnWidth(1, 22 * 256);

            HSSFCell cellTitle3 = rowTitle.createCell(2);
            cellTitle3.setCellValue("是否包含下级");
            sheet.setColumnWidth(2, 22 * 256);

            HSSFCell cellTitle4 = rowTitle.createCell(3);
            cellTitle4.setCellValue("周工作日");
            sheet.setColumnWidth(3, 22 * 256);

            HSSFCell cellTitle5 = rowTitle.createCell(4);
            cellTitle5.setCellValue("开始时间");
            sheet.setColumnWidth(4, 22 * 256);

            HSSFCell cellTitle6 = rowTitle.createCell(5);
            cellTitle6.setCellValue("考勤时间");
            sheet.setColumnWidth(5, 22 * 256);

            HSSFCell cellTitle7 = rowTitle.createCell(6);
            cellTitle7.setCellValue("结束时间");
            sheet.setColumnWidth(6, 22 * 256);

            HSSFCell cellTitle8 = rowTitle.createCell(7);
            cellTitle8.setCellValue("考勤类型");
            sheet.setColumnWidth(7, 22 * 256);

            HSSFCell cellTitle9 = rowTitle.createCell(8);
            cellTitle9.setCellValue("考勤分类");
            sheet.setColumnWidth(8, 22 * 256);

            HSSFCell cellTitle10 = rowTitle.createCell(9);
            cellTitle10.setCellValue("是否需要提醒");
            sheet.setColumnWidth(9, 22 * 256);


            for(int i=0; i<page.size(); i++){
                AlarmConfig ac = page.get(i);

                HSSFRow rowContent = sheet.createRow(i + 1);
                HSSFCell cellContent1 = rowContent.createCell(0);
                cellContent1.setCellValue(i+1);

                //单位
                HSSFCell cellContent2 = rowContent.createCell(1);
                if (ac.getCompanyName() != null) {
                    cellContent2.setCellValue(ac.getCompanyName());
                }
                //是否包含下级
                HSSFCell cellContent3 = rowContent.createCell(2);
                if (ac.getSubordinate() != null) {
                    cellContent3.setCellValue(ac.getSubordinate()?"是":"否");
                }
                //周工作日
                HSSFCell cellContent4 = rowContent.createCell(3);
                if (ac.getWeekdays() != null) {
                    cellContent4.setCellValue(ac.getWeekdays());
                }
                //开始时间
                HSSFCell cellContent5 = rowContent.createCell(4);
                if (ac.getStartTime() != null) {
                    cellContent5.setCellValue(ac.getStartTime());
                }
                //考勤时间
                HSSFCell cellContent6 = rowContent.createCell(5);
                if (ac.getAttendanceTime() != null) {
                    cellContent6.setCellValue(ac.getAttendanceTime());
                }
                //结束时间
                HSSFCell cellContent7 = rowContent.createCell(6);
                if (ac.getEndTime() != null) {
                    cellContent7.setCellValue(ac.getEndTime());
                }
                //考勤类型
                HSSFCell cellContent8 = rowContent.createCell(7);
                if (ac.getAttendanceType() != null) {
                    cellContent8.setCellValue(ac.getAttendanceType() == 1?"内勤":"外勤");
                }
                //考勤分类
                HSSFCell cellContent9 = rowContent.createCell(8);
                if (ac.getClassifier() != null) {
                    cellContent9.setCellValue(ac.getClassifier() == 1?"上班时间":"下班时间");
                }
                //考勤分类
                HSSFCell cellContent10 = rowContent.createCell(9);
                if (ac.getNeedMeasureTemperature() != null) {
                    cellContent10.setCellValue(ac.getNeedMeasureTemperature()?"是":"否");
                }
            }

            //todo 将wb保存到oss
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            workbook.write(output);

            byte[] buffer = output.toByteArray();
            ByteArrayInputStream input = new ByteArrayInputStream(buffer);
            //格式化
            SimpleDateFormat sim = new SimpleDateFormat("yyyyMMddHHmmss");
            String fileName = "导出考勤时间设置数据" + sim.format(new Date()) + ".xls";
            String downloadUrl = OSSUtil.upload(ossConfig, "import", fileName, input);

            msgResult.setData(downloadUrl);
            msgResult.setResult(true);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }


        return msgResult;
    }


    @ApiOperation(value="导入考勤时间设置")
    @PostMapping("importXls")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uploadFile",value = "上传文件", required = true,paramType="form", dataType = "__file")
    })
    public MessageResult<String> importXls(MultipartFile uploadFile,
                                           String companyId,
                                           @RequestAttribute String subject){
        User user = userService.get(subject);
        MessageResult<String> msgResult = new MessageResult<>();

        try {
            POIUtils poiUtils = new POIUtils(uploadFile.getInputStream());
            int sheetIndex = 0;
            Sheet sheet1 = poiUtils.getSheetAt(sheetIndex);

            String[] colNames = new String[]{"是否包含下级单位","周工作日","开始时间","考勤时间","结束时间","考勤类型","考勤分类","是否需要提醒"};
            Map<String,Integer> headerMap = new HashMap<>();

            Row headerRow = sheet1.getRow(0);

            for (int i=0;i<colNames.length;i++) {
                String colName = colNames[i];

                for (int j = 0; j < headerRow.getLastCellNum(); j++) {
                    String title = headerRow.getCell(j).getStringCellValue();

                    if (title.indexOf(colName)!=-1){
                        headerMap.put(colName, j);
                        break;
                    }
                }
            }

            int affectCount = 0;
            int failCount = 0;
            int validateColIndex = 9;

            for(int rowIndex=1 ; rowIndex<=sheet1.getLastRowNum(); rowIndex++){
                try {
                    String subordinateName = "";

                    if(headerMap.containsKey("是否包含下级单位")){
                        subordinateName = poiUtils.getCellValue(sheetIndex,rowIndex,headerMap.get("是否包含下级单位")).toString().replace(" ","");
                    }

                    String weekdays = "";

                    if(headerMap.containsKey("周工作日")) {
                        weekdays = poiUtils.getCellValue(sheetIndex, rowIndex, headerMap.get("周工作日")).toString().replace(" ", "");
                    }

                    String startTime = "";

                    if(headerMap.containsKey("开始时间")) {
                        startTime = poiUtils.getCellValue(sheetIndex, rowIndex, headerMap.get("开始时间")).toString().replace(" ", "");
                    }

                    String attendanceTime = "";

                    if(headerMap.containsKey("考勤时间")) {
                        attendanceTime = poiUtils.getCellValue(sheetIndex, rowIndex, headerMap.get("考勤时间")).toString().replace(" ", "");
                    }

                    String endTime = "";

                    if(headerMap.containsKey("结束时间")) {
                        endTime = poiUtils.getCellValue(sheetIndex, rowIndex, headerMap.get("结束时间")).toString().replace(" ", "");
                    }

                    String attendanceTypeName = "";

                    if(headerMap.containsKey("考勤类型")) {
                        attendanceTypeName = poiUtils.getCellValue(sheetIndex, rowIndex, headerMap.get("考勤类型")).toString().replace(" ", "");
                    }

                    String classifierName = "";

                    if(headerMap.containsKey("考勤分类")) {
                        classifierName = poiUtils.getCellValue(sheetIndex, rowIndex, headerMap.get("考勤分类")).toString().replace(" ", "");
                    }

                    String needMeasureTemperatureName = "";

                    if(headerMap.containsKey("是否需要提醒")) {
                        needMeasureTemperatureName = poiUtils.getCellValue(sheetIndex, rowIndex, headerMap.get("是否需要提醒")).toString().replace(" ", "");
                    }

                    CompanyInfo companyInfo = companyInfoService.get(companyId);

                    if(companyInfo == null){
                        sheet1.getRow(rowIndex).createCell(validateColIndex).setCellValue("公司不存在!");
                        failCount++;
                        continue;
                    }else{
                        companyId = companyInfo.getId();
                    }

                    Boolean subordinate = false;
                    Integer attendanceType = null;
                    Integer classifier = null;
                    Boolean needMeasureTemperature = false;
                    if(StringUtils.isNotEmpty(subordinateName)){
                        if("是".equals(subordinateName)){
                            subordinate = true;
                        }else{
                            subordinate = false;
                        }
                    }

                    if(StringUtils.isEmpty(startTime)){
                        sheet1.getRow(rowIndex).createCell(validateColIndex).setCellValue("请填写开始时间!");
                        failCount++;
                        continue;
                    }

                    if(StringUtils.isEmpty(attendanceTime)){
                        sheet1.getRow(rowIndex).createCell(validateColIndex).setCellValue("请填写考勤时间!");
                        failCount++;
                        continue;
                    }

                    if(StringUtils.isEmpty(endTime)){
                        sheet1.getRow(rowIndex).createCell(validateColIndex).setCellValue("请填写结束时间!");
                        failCount++;
                        continue;
                    }

                    if(StringUtils.isNotEmpty(attendanceTypeName)){
                        if("内勤".equals(attendanceTypeName)){
                            attendanceType = 1;
                        }else if("外勤".equals(attendanceTypeName)){
                            attendanceType = 2;
                        }
                    }else{
                        sheet1.getRow(rowIndex).createCell(validateColIndex).setCellValue("请填写考勤类型!");
                        failCount++;
                        continue;
                    }

                    if(StringUtils.isNotEmpty(classifierName)){
                        if("上班时间".equals(classifierName)){
                            classifier = 1;
                        }else if("下班时间".equals(classifierName)){
                            classifier = 2;
                        }
                    }else{
                        sheet1.getRow(rowIndex).createCell(validateColIndex).setCellValue("请填写考勤分类!");
                        failCount++;
                        continue;
                    }

                    if(StringUtils.isNotEmpty(needMeasureTemperatureName)){
                        if("是".equals(needMeasureTemperatureName)){
                            needMeasureTemperature = true;
                        }else{
                            needMeasureTemperature = false;
                        }
                    }


                    //用户身份
                    AlarmConfig ac = new AlarmConfig();
                    ac.setId(UUID.randomUUID().toString());
                    ac.setCompanyId(companyId);
                    ac.setSubordinate(subordinate);
                    ac.setWeekdays(weekdays);
                    ac.setStartTime(startTime);
                    ac.setAttendanceTime(attendanceTime);
                    ac.setEndTime(endTime);
                    ac.setAttendanceType(attendanceType);
                    ac.setClassifier(classifier);
                    ac.setNeedMeasureTemperature(needMeasureTemperature);
                    ac.setDelFlag(false);
                    ac.setCreateBy(subject);
                    ac.setCreateTime(new Date());

                    //保存
                    alarmConfigService.insert(ac);
                    affectCount++;
                }
                catch(Exception innerEx){
                    logger.error(innerEx.getMessage(),innerEx);
                }
            }

            if (failCount>0){
                //有导入失败的记录
                msgResult.setResult(false);
                msgResult.setMessage("数据成功导入" + affectCount + "条,有" + failCount + "条数据未导入成功，错误原因请查看报表。");

                //todo 只保留错误数据的sheet
                Workbook wb = poiUtils.exportErrorXls(sheetIndex,validateColIndex,1 + affectCount + failCount);

                //todo 将wb保存到oss
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                wb.write(output);

                byte[] buffer = output.toByteArray();
                ByteArrayInputStream input = new ByteArrayInputStream(buffer);

                //格式化holidayInfo
                SimpleDateFormat sim = new SimpleDateFormat("yyyyMMddHHmmss");
                String fileName = "error" + sim.format(new Date()) + ".xls";
                String downloadUrl = OSSUtil.upload(ossConfig,"import",fileName,input);

                //todo 返回导入失败报表下载链接
                msgResult.setData(downloadUrl);
            }
            else{
                msgResult.setResult(true);
                msgResult.setMessage("数据成功导入" + affectCount + "条");
            }
        }
        catch(Exception ex){
            logger.error(ex.getMessage(),ex);

            msgResult.setResult(false);
            msgResult.setMessage(ex.getMessage());
        }

        return msgResult;
    }
}
