package com.winsun.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.winsun.auth.core.annotion.Permission;
import com.winsun.auth.core.base.controller.BaseController;
import com.winsun.auth.core.common.model.ResponseData;
import com.winsun.auth.core.shiro.ShiroUser;
import com.winsun.auth.core.util.DateUtil;
import com.winsun.auth.core.util.IOUtils;
import com.winsun.bean.YxtCoupon;
import com.winsun.mapper.YxtCouponMapper;
import com.winsun.utils.ExcelDealUtils;
import com.winsun.utils.ImportExcel;
import com.winsun.utils.MyBatisPlusUpdateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 兑换券校检
 *
 * @Author: xiangli
 * @Date:
 */
@Slf4j
@RestController
@RequestMapping("/yxtCoupon")
public class YxtCouponController extends BaseController {
    /**
     * 导入
     */
    private static final int HEADER_NUM = -1;
    private static final int SHEET_INDEX = 0;
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    /**
     * KPI信息模板列名
     */
    private static String SL_cardNumber = "兑换券账号";
    private static String SL_password = "密码";
    private static String SL_updateDate = "有效截止日期";
    private static String SL_state = "出售状态(1:未售出,2:已售出,3:售出中)";
    private static String SL_validityPeriod = "有效截止日期";
    private static String SL_shelfState = "上架状态(1:已上架,2:已下架)";
    private static String SL_delFlag = "是否删除(0:未删除，1:已删除)";

    @Autowired
    private YxtCouponMapper yxtCouponMapper;

    @Autowired
    @Qualifier("redisStringTemplate")
    private RedisTemplate redisTemplate;

    /**
     * 兑换券添加
     *
     * @param yxtCoupon 添加对象json字符串
     * @return
     */
    @Permission(menuname = "添加兑换券信息", value = "insert", method = RequestMethod.POST)
    public ResponseData<String> insertProduct(@RequestParam("yxtCoupon") String yxtCoupon) {
        ShiroUser user = getShiroUser();
        if (!user.getRoleNames().stream().anyMatch(roleName -> StringUtils.equalsAny(roleName, "超级管理员"))) {
            return ResponseData.error("无数据权限");
        }
        YxtCoupon yxt = JSON.parseObject(yxtCoupon, YxtCoupon.class);
        yxt.setUpdateDate(new Date());
        yxtCouponMapper.insert(yxt);
        return ResponseData.success("添加成功！");
    }

    /**
     * kpi删除
     *
     * @param id 需要删除的id
     * @return
     */
    @Permission(menuname = "删除兑换券信息", value = "delete", method = RequestMethod.POST)
    public ResponseData<String> deleteProduct(@RequestParam(name = "id", required = false) String id, @RequestParam(name = "isdel", required = false) String isdel) {
        ShiroUser user = getShiroUser();
        if (!user.getRoleNames().stream().anyMatch(roleName -> StringUtils.equalsAny(roleName, "超级管理员"))) {
            return ResponseData.error("无数据权限");
        }
        if(StringUtils.isNotBlank(id)){
            yxtCouponMapper.deleteById(Integer.valueOf(id));
            return ResponseData.success("操作成功！");
        }
        return ResponseData.success("操作成功!");
    }

    /**
     * 兑换券信息编辑
     *
     * @param yxtCoupon 编辑对象json字符串
     * @return
     */
    @Permission(menuname = "修改兑换券信息", value = "update", method = RequestMethod.POST)
    public ResponseData<String> updateProduct(@RequestParam("yxtCoupon") String yxtCoupon) {
        ShiroUser user = getShiroUser();
        if (!user.getRoleNames().stream().anyMatch(roleName -> StringUtils.equalsAny(roleName, "超级管理员"))) {
            return ResponseData.error("无数据权限");
        }
        YxtCoupon pro = JSON.parseObject(yxtCoupon, YxtCoupon.class);
        Wrapper wrapper = new EntityWrapper<>();
        wrapper.eq("id", pro.getId());
        Map<String, Object> dataMapping = new HashMap<>();
        dataMapping.put("card_number", pro.getCardNumber());
        dataMapping.put("password", pro.getPassword());
        dataMapping.put("update_date", pro.getUpdateDate());
        dataMapping.put("state", pro.getState());
        dataMapping.put("validity_period", pro.getValidityPeriod());
        dataMapping.put("shelf_state", pro.getShelfState());
        dataMapping.put("del_flag", pro.getDelFlag());
        yxtCouponMapper.updateForSet(MyBatisPlusUpdateUtils.toUpdateSet(dataMapping), wrapper);
        return ResponseData.success("修改成功！");
    }

    /**
     * @param card
     * @param state
     * @param shelfState
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Permission(menuname = "查询兑换券信息", value = "list", method = RequestMethod.POST)
    public ResponseData<Page<YxtCoupon>> listProduct(
            @RequestParam(name = "card", required = false) String card,
            @RequestParam(name = "state", required = false) String state,
            @RequestParam(name = "shelfState", required = false) String shelfState,
            @RequestParam(name = "pageNo") int pageNo, @RequestParam(name = "pageSize") int pageSize) {
        ShiroUser user = getShiroUser();
        if (!user.getRoleNames().stream().anyMatch(roleName -> StringUtils.equalsAny(roleName, "超级管理员"))) {
            return ResponseData.error("无数据权限");
        }

        Page<YxtCoupon> page = new Page<>(pageNo, pageSize);
        List<YxtCoupon> dataList = new LinkedList<>();

        Wrapper<YxtCoupon> yxtCouponWrapper = new EntityWrapper<>();
        yxtCouponWrapper.like(StringUtils.isNotBlank(card), "card_number", card, SqlLike.DEFAULT);
        yxtCouponWrapper.eq(StringUtils.isNotBlank(state), "state", state);
        yxtCouponWrapper.eq(StringUtils.isNotBlank(shelfState), "shelf_state", shelfState);
        List<YxtCoupon> yxtCouponList = yxtCouponMapper.selectList(yxtCouponWrapper);

        if (yxtCouponList.size() < pageSize) {
            dataList = yxtCouponList;
        } else {
            dataList = yxtCouponList.subList((pageNo - 1) * pageSize, pageNo * pageSize);
        }

        page.setRecords(dataList);
        page.setTotal(yxtCouponList.size());
        return ResponseData.success(page, "查询成功！");
    }

    /**
     * @param card
     * @param state
     * @param shelfState
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Permission(menuname = "导出兑换券信息", value = "excelOut", method = RequestMethod.POST)
    public void excelOut(
            @RequestParam(name = "card", required = false) String card,
            @RequestParam(name = "state", required = false) String state,
            @RequestParam(name = "shelfState", required = false) String shelfState,
            @RequestParam(name = "pageNo") int pageNo, @RequestParam(name = "pageSize") int pageSize
    ) throws IOException {
        ShiroUser user = getShiroUser();
        List<Map<String, Object>> list = new LinkedList<>();

        Wrapper<YxtCoupon> yxtCouponWrapper = new EntityWrapper<>();
        yxtCouponWrapper.like(StringUtils.isNotBlank(card), "card_number", card, SqlLike.DEFAULT);
        yxtCouponWrapper.eq(StringUtils.isNotBlank(state), "state", state);
        yxtCouponWrapper.eq(StringUtils.isNotBlank(shelfState), "shelf_state", shelfState);
        List<YxtCoupon> yxtCouponList = yxtCouponMapper.selectList(yxtCouponWrapper);

        for (YxtCoupon yxt : yxtCouponList) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", yxt.getId());
            map.put("cardNumber", yxt.getCardNumber());
            map.put("password", yxt.getPassword());
            map.put("updateDate", DateUtil.formatDate(yxt.getUpdateDate(),"yyyy-mm-dd"));
            Integer state0 = yxt.getState();
            if(state0 == 1){
                map.put("state", "未售出");
            }else if(state0 == 2){
                map.put("state", "已售出");
            }else{
                map.put("state", "售出中");
            }
            map.put("validityPeriod", DateUtil.formatDate(yxt.getValidityPeriod(),"yyyy-mm-dd"));
            Integer shelfState0 = yxt.getShelfState();
            if(shelfState0 == 1){
                map.put("shelfState", "已上架");
            }else{
                map.put("shelfState", "已下架");
            }
            Integer delFlag0 = yxt.getShelfState();
            if(delFlag0 == 0){
                map.put("delFlag", "未删除");
            }else{
                map.put("delFlag", "已删除");
            }
            list.add(map);
        }
        ServletOutputStream os = null;
        XSSFWorkbook workbook = ExcelDealUtils.getWorkBook(ExcelDealUtils.exchangeCouponExcel("兑换券清单"), list);
        try {
            HttpServletResponse response = getHttpServletResponse();
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            os = response.getOutputStream();
            workbook.write(os);
            os.flush();
        } catch (Exception e) {
            log.error("文件出错！" + e.getMessage(), e);
        } finally {
            IOUtils.closeQuite(workbook, os);
        }
    }

    /**
     * 受理订单模板下载
     *
     * @return
     */
    @Permission(menuname = "兑换券信息导入模板", method = RequestMethod.POST, value = "downloadMoBan")
    public ResponseData downloadMoBan() {
        ArrayList<String> columns = new ArrayList<>();
        columns.add(SL_cardNumber);
        columns.add(SL_password);
        columns.add(SL_state);
        columns.add(SL_shelfState);
        columns.add(SL_validityPeriod);
        columns.add(SL_updateDate);
        columns.add(SL_delFlag);
        ServletOutputStream os = null;
        XSSFWorkbook workbook = new XSSFWorkbook();
        try {
            //创建工作表
            XSSFSheet sheet = workbook.createSheet("兑换券信息模板");
            sheet.setColumnWidth(0, 6000);
            sheet.setColumnWidth(1, 6000);
            sheet.setColumnWidth(2, 6000);
            sheet.setColumnWidth(3, 6000);
            sheet.setColumnWidth(4, 6000);
            sheet.setColumnWidth(5, 6000);
            sheet.setColumnWidth(6, 6000);
            //下拉选项
            /*List<String> fengju = new ArrayList<>();
            fengju.add("受理不成功");
            fengju.add("受理成功");
            sheet = this.getXSSFSheet(sheet, fengju, 1, 1);*/
            //添加表头
            final XSSFRow row = sheet.createRow(0);
            XSSFCellStyle cellStyle = workbook.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            columns.forEach(val -> {
                XSSFCell cell = row.createCell(Math.max(row.getLastCellNum(), 0));
                cell.setCellValue(val);
            });
            HttpServletResponse response = getHttpServletResponse();
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;fileName=data.xlsx");
            os = response.getOutputStream();
            workbook.write(os);
            os.flush();
        } catch (IOException e) {
            log.error("兑换券信息模板文件出错！" + e.getMessage(), e);
        } finally {
            IOUtils.closeQuite(workbook, os);
        }
        return ResponseData.error("兑换券信息模板出错");
    }

    XSSFSheet getXSSFSheet(XSSFSheet sheet, List<String> datas, int firstcol, int lastcol) {
        if (datas.size() == 0) {
            return sheet;
        }
        String[] strdata = new String[datas.size()];
        for (int i = 0; i < datas.size(); i++) {
            strdata[i] = datas.get(i);
        }
        XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(sheet);
        XSSFDataValidationConstraint dvConstraint1 = (XSSFDataValidationConstraint) dvHelper.createExplicitListConstraint(strdata);
        CellRangeAddressList addressList = new CellRangeAddressList(1, 20000, firstcol, lastcol);
        XSSFDataValidation validation = (XSSFDataValidation) dvHelper.createValidation(dvConstraint1, addressList);
        sheet.addValidationData(validation);
        return sheet;
    }

    /**
     * 受理订单
     *
     * @param file 上传的数据文件
     * @return
     */
    @Permission(menuname = "上传数据", value = "importDate", method = RequestMethod.POST)
    public ResponseData<String> updateDatas(@RequestParam(name = "file") MultipartFile file) {
        StringBuffer error = new StringBuffer();
        if (!StringUtils.endsWithAny(file.getOriginalFilename(), "xlsx", "xls")) {
            return ResponseData.error("手工上传数据仅支持Excel文件，其他格式不支持！");
        }
        ShiroUser user = getShiroUser();
        // 当前是否有数据权限
        boolean hasDataPermission = user.getRoleNames().stream().anyMatch(data -> StringUtils.equalsAny(data, "活动上单员", "数据管理员", "超级管理员"));
        if (!hasDataPermission) {
            return ResponseData.error("无数据权限！");
        }
        ImportExcel importExcel = null;
        try {
            importExcel = new ImportExcel(file, HEADER_NUM, SHEET_INDEX);
        } catch (Exception e) {
            log.error("兑换券信息导入异常", e.getMessage());
            return ResponseData.error("导入异常！");
        }
        List<Map<String, Object>> listMap = importExcel.getDataListMap();
        if (listMap.size() == 1) {
            return ResponseData.error("文件不能为空");
        }
        if (!listMap.get(0).get("a").toString().equals(SL_cardNumber)) {
            return ResponseData.error("模板不对，请选择正确的模板！");
        }
        if (!listMap.get(0).get("b").toString().equals(SL_password)) {
            return ResponseData.error("模板不对，请选择正确的模板！");
        }
        if (!listMap.get(0).get("c").toString().equals(SL_state)) {
            return ResponseData.error("模板不对，请选择正确的模板！");
        }
        if (!listMap.get(0).get("d").toString().equals(SL_shelfState)) {
            return ResponseData.error("模板不对，请选择正确的模板！");
        }
        if (!listMap.get(0).get("e").toString().equals(SL_validityPeriod)) {
            return ResponseData.error("模板不对，请选择正确的模板！");
        }
        if (!listMap.get(0).get("f").toString().equals(SL_updateDate)) {
            return ResponseData.error("模板不对，请选择正确的模板！");
        }
        if (!listMap.get(0).get("g").toString().equals(SL_delFlag)) {
            return ResponseData.error("模板不对，请选择正确的模板！");
        }

        if (listMap.get(0).size() != 7) {
            return ResponseData.error("模板不对，请选择正确的模板！");
        }

        List<String> accountList = new LinkedList<>();
        List<Map<String, Object>> sysUserList = new LinkedList<>();
        //校验数据
        try {
            //校验数据
            for (int i = 1; i < listMap.size(); i++) {
                Map<String, Object> temp = listMap.get(i);
                if (!temp.containsKey("a")) {
                    return ResponseData.error("第" + (i + 1) + "行的兑换券账号不能为空");
                }
                if (StringUtils.isBlank(temp.get("a").toString())) {
                    return ResponseData.error("第" + (i + 1) + "行的兑换券账号不能为空");
                }
                if (!temp.containsKey("b")) {
                    return ResponseData.error("第" + (i + 1) + "行的密码不能为空");
                }
                if (StringUtils.isBlank(temp.get("b").toString())) {
                    return ResponseData.error("第" + (i + 1) + "行的密码不能为空");
                }
                if (!temp.containsKey("c")) {
                    return ResponseData.error("第" + (i + 1) + "行的出售状态不能为空");
                }
                if (StringUtils.isBlank(temp.get("c").toString())) {
                    return ResponseData.error("第" + (i + 1) + "行的出售状态不能为空");
                }
                if (!temp.containsKey("d")) {
                    return ResponseData.error("第" + (i + 1) + "行的上架状态不能为空");
                }
                if (StringUtils.isBlank(temp.get("d").toString())) {
                    return ResponseData.error("第" + (i + 1) + "行的上架状态不能为空");
                }
                if (!temp.containsKey("e")) {
                    return ResponseData.error("第" + (i + 1) + "行的有限日期不能为空");
                }
                if (StringUtils.isBlank(temp.get("e").toString())) {
                    return ResponseData.error("第" + (i + 1) + "行的有限日期不能为空");
                }
                if (!temp.containsKey("f")) {
                    return ResponseData.error("第" + (i + 1) + "行的上传时间不能为空");
                }
                if (!temp.containsKey("g")) {
                    return ResponseData.error("第" + (i + 1) + "行的是否删除不能为空");
                }
                if (StringUtils.isBlank(temp.get("g").toString())) {
                    return ResponseData.error("第" + (i + 1) + "行的是否删除不能为空");
                }

            }
            //检查excel表中是否有重复人员编号
            int size = listMap.size();
            Set<String> accountSet = new HashSet<>(size);
            for (int i = 0; i < size; i++) {
                Map<String, Object> temp = listMap.get(i);
                accountSet.add((String) temp.get("a"));
            }
            if (accountSet.size() != size) {
                return ResponseData.error("文件中有重复的兑换券账号，请确认兑换券账号不能重复!");
            }
        } catch (Exception e) {
            log.error("兑换券信息导入异常", e.getMessage());
            return ResponseData.error("导入异常！");
        }
        Wrapper<YxtCoupon> yxtCouponWrapper = new EntityWrapper<>();
        List<YxtCoupon> yxtCouponList = yxtCouponMapper.selectList(yxtCouponWrapper);
        int number = 0;
        for (int i = 1; i < listMap.size(); i++) {
            Map<String, Object> map = listMap.get(i);
            YxtCoupon yxt = new YxtCoupon();
            String cardNumber = map.get("a").toString();
            yxt.setCardNumber(cardNumber);
            String password = map.get("b").toString();
            yxt.setPassword(password);
            String state = map.get("c").toString();
            if(state.equals("未售出")){
                yxt.setState(1);
            }else if(state.equals("已售出")){
                yxt.setState(2);
            }else{
                yxt.setState(3);
            }
            String shelfState = map.get("d").toString();
            if(shelfState.equals("已上架")){
                yxt.setShelfState(1);
            }else{
                yxt.setShelfState(2);
            }
            Date validityPeriod = DateUtil.parse(map.get("e").toString(), "yyyy-mm-dd");
            yxt.setValidityPeriod(validityPeriod);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");// 格式化时间
            Date updateDate = DateUtil.parse(sdf.format(new Date()),"yyyy-mm-dd");
            yxt.setUpdateDate(updateDate);
            String delFlag = map.get("g").toString();
            if(delFlag.equals("未删除")){
                yxt.setDelFlag(0);
            }else{
                yxt.setDelFlag(1);
            }
            boolean isUpdate = false;
            for (YxtCoupon yxtCoupon : yxtCouponList) {
                if(yxtCoupon.getCardNumber().equals(cardNumber)){
                    yxt.setId(yxtCoupon.getId());
                    isUpdate = true;
                    break;
                }
            }
            try {
                if(isUpdate){
                    Wrapper<YxtCoupon> wrapper = new EntityWrapper<>();
                    wrapper.eq("id", yxt.getId());
                    /*wrapper11.eq("id", yxt.getId());
                    Map<String, Object> dataMapping11 = new HashMap<>();
                    dataMapping11.put("card_number", yxt.getCardNumber());
                    dataMapping11.put("password", yxt.getPassword());
                    dataMapping11.put("updateDate", yxt.getUpdateDate());
                    dataMapping11.put("state", yxt.getState());
                    dataMapping11.put("validityPeriod", yxt.getValidityPeriod());
                    dataMapping11.put("shelfState", yxt.getShelfState());
                    yxtCouponMapper.updateForSet(MyBatisPlusUpdateUtils.toUpdateSet(dataMapping11), wrapper11);*/
                    yxtCouponMapper.update(yxt,wrapper);
                    number++;
                }else{
                    Integer integer = yxtCouponMapper.insert(yxt);
                    if (integer == 1) {
                        number++;
                    } else {
                        error.append("第" + (i + 1) + "行的更新失败,");
                    }
                }
            }catch (Exception e){
                log.info(e.getMessage());
                error.append("第" + (i + 1) + "行的更新失败,");
            }


        }
        error.append("成功更新" + number + "条数据！");
        return ResponseData.success(error.toString(), "导入完成");
    }
}
