package cn.chnmuseum.party.web.controller;

import cn.chnmuseum.party.common.log.MethodLog;
import cn.chnmuseum.party.common.log.OperModule;
import cn.chnmuseum.party.common.log.OperType;
import cn.chnmuseum.party.common.util.ExportExcelUtil;
import cn.chnmuseum.party.common.util.RSAUtils;
import cn.chnmuseum.party.common.validator.groups.Update;
import cn.chnmuseum.party.model.TArea;
import cn.chnmuseum.party.model.TBoxOperation;
import cn.chnmuseum.party.model.TUser;
import cn.chnmuseum.party.service.TAreaService;
import cn.chnmuseum.party.service.TBoxOperationService;
import cn.chnmuseum.party.service.impl.TUserServiceImpl;
import cn.chnmuseum.party.web.controller.base.BaseController;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <pre>
 * 机顶盒运维信息 前端控制器
 * </pre>
 *
 * @author Danny Lee
 * @since 2021-03-25
 */
@Slf4j
@RestController
@RequestMapping("/boxOperation")
@Api(tags = {"机顶盒运维信息操作接口"})
@Validated
public class TBoxOperationController extends BaseController {

    @Resource
    private TBoxOperationService tBoxOperationService;

    @Resource
    private TUserServiceImpl userService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    TAreaService areaService;

    private static final String SHIRO_JWT_TOKEN = "shiro:jwt:token:";

    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "_index", value = "分页起始偏移量", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "_size", value = "返回条数", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "organId", value = "所属单位", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "status", value = "状态 1.未激活 2.已激活 3.故障", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "areaId", value = "区域", paramType = "query", dataType = "String")
    })
    @PostMapping("/selectPageList")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/selectPageList")
    @ApiOperation(value = "获取机顶盒基础信息分页列表", notes = "获取机顶盒基础信息分页列表")
    @MethodLog(operModule = OperModule.STBBASE, operType = OperType.SELECT)
    public Map<String, Object> selectPageList(String organId, String areaId, LocalDate beginDate, LocalDate endDate) {
        TUser user1 = getcurUser();
        TUser user = new TUser();
        if (StringUtils.isNotBlank(organId)) {
            user.setOrgId(organId);
        }
        if (StringUtils.isNotBlank(areaId)) {
            user.setAreaId(areaId);
        }
        //设置数据权限
//        if (StringUtils.isNotBlank(user1.getAreaId())) {
//            String areaId1 = getAreaId(user1.getAreaId());
//            user.setAreaName(areaId1);
//        }
        if (beginDate != null && endDate != null) {
            user.setBeginDate(beginDate.atTime(0, 0, 0));
            user.setEndDate(endDate.atTime(23, 59, 59));
        }
        if (!user1.getRoleList().contains("1")) {
            user.setOrgCode(user1.getOrgCode());
        }
        try {
            Page<TBoxOperation> page = tBoxOperationService.selectBoxPage(getPage(), user);
            return getResult(page);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getFailResult();
    }

    @PostMapping("/add")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/add")
    @ApiOperation(value = "添加机顶盒运维信息", notes = "添加机顶盒运维信息")
    @MethodLog(operModule = OperModule.STBOPERATION, operType = OperType.ADD)
    public Map<String, Object> saveTBoxOperation(TBoxOperation tBoxOperation) {
        // 保存业务节点信息
        boolean result;
        try {
            if (tBoxOperation != null && StringUtils.isNotBlank(tBoxOperation.getMac())) {
                tBoxOperation.setMac(tBoxOperation.getMac().toUpperCase());
            }
            final ArrayList<String> rsaKeys = RSAUtils.createRSAKeys();
            tBoxOperation.setPublicKey(rsaKeys.get(0));
            tBoxOperation.setPrivateKey(rsaKeys.get(1));
            result = tBoxOperationService.save(tBoxOperation);
            if (!result) {
                return getFailResult();
            }
            return getSuccessResult();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 保存失败
        return getFailResult();
    }

    @PutMapping("/update")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/update")
    @ApiOperation(value = "修改机顶盒运维信息", notes = "修改机顶盒运维信息")
    @MethodLog(operModule = OperModule.STBOPERATION, operType = OperType.ACTIVATION)
    public Map<String, Object> updateTBoxOperation(@Validated(value = Update.class) TBoxOperation tBoxOperation) {
        Map<String, Object> resultMap = new LinkedHashMap<String, Object>();
        try {
            if (tBoxOperation != null && StringUtils.isNotBlank(tBoxOperation.getMac())) {
                tBoxOperation.setMac(tBoxOperation.getMac().toUpperCase());
            }
            if (2 == tBoxOperation.getStatus()) {
                TBoxOperation byId = tBoxOperationService.getById(tBoxOperation.getId());
                if (byId.getMac() != null && !"".equals(byId.getMac()) && !byId.getMac().equals(tBoxOperation.getMac())) {
                    resultMap.put("resultCode", "400");
                    resultMap.put("message", "此账号已绑定机顶盒!");
                    return resultMap;
                }
                UpdateWrapper<TBoxOperation> wrapper = new UpdateWrapper<>();
                wrapper.eq("mac", tBoxOperation.getMac());
                TBoxOperation one = tBoxOperationService.getOne(wrapper);
                if (one != null && !one.getOrganId().equals(tBoxOperation.getOrganId())) {
                    resultMap.put("resultCode", "400");
                    resultMap.put("message", "此mac地址已绑定账号!");
                    return resultMap;
                }
            }
            if (3 == tBoxOperation.getStatus()) {
                tBoxOperation.setMac(null);
                TUser u = userService.getOne(new UpdateWrapper<TUser>().eq("org_id", tBoxOperation.getOrganId()).eq("type", 3).eq("is_deleted", false));
                Set<String> keys = stringRedisTemplate.keys(SHIRO_JWT_TOKEN + "*");
                ValueOperations<String, String> value = stringRedisTemplate.opsForValue();
                for (String key : keys) {
                    if (u.getId().equals(value.get(key))) {
                        stringRedisTemplate.delete(key);
                    }
                }
            }
            boolean flag = tBoxOperationService.updateById(tBoxOperation);
            UpdateWrapper<TUser> wrapper = new UpdateWrapper<>();
            wrapper.eq("org_id", tBoxOperation.getOrganId());
            wrapper.eq("type", "3");
            TUser user = userService.getOne(wrapper);
            String password = user.getPassword();
            if (flag) {
                return getResult(password);
            }
            return getFailResult();
        } catch (Exception e) {
            return getFailResult();
        }
    }

    @DeleteMapping("/delete")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/delete")
    @ApiOperation(value = "根据ID删除机顶盒运维信息", notes = "根据ID删除机顶盒运维信息")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "id", value = "标识ID", paramType = "query", dataType = "String")
    })
    @MethodLog(operModule = OperModule.STBOPERATION, operType = OperType.DELETE)
    public Map<String, Object> deleteTBoxOperation(String id) {
        boolean result;
        try {
            result = tBoxOperationService.removeById(id);
            if (!result) {
                return getFailResult();
            }
            return getSuccessResult();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getFailResult();
    }

    @GetMapping("/getList")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/getList")
    @ApiOperation(value = "获取机顶盒运维信息全部列表(无分页)", notes = "获取机顶盒运维信息全部列表(无分页)")
    @MethodLog(operModule = OperModule.STBOPERATION, operType = OperType.SELECT)
    public Map<String, Object> getTBoxOperationList(String status) {
        List<TBoxOperation> tBoxOperationList = null;
        TUser user = getcurUser();

        try {
            if ("4".equals(user.getType())) {
                //设置数据权限
                String areaId = user.getAreaId();
                tBoxOperationList = tBoxOperationService.getList(status, getAreaId(areaId));
            } else {
                tBoxOperationList = tBoxOperationService.getList(status, null);
            }

            return getResult(tBoxOperationList);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getFailResult();
    }

    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "_index", value = "分页起始偏移量", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "_size", value = "返回条数", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "organId", value = "所属单位", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "status", value = "状态 1.未激活 2.已激活 3.故障", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "areaId", value = "区域", paramType = "query", dataType = "String")
    })
    @PostMapping("/getPageList")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/getPageList")
    @ApiOperation(value = "获取机顶盒运维信息分页列表", notes = "获取机顶盒运维信息分页列表")
    @MethodLog(operModule = OperModule.STBOPERATION, operType = OperType.SELECT)
    public Map<String, Object> getTBoxOperationPageList(String organId, Integer status, String areaId) {
        TUser user = getcurUser();
        TBoxOperation tBoxOperation = new TBoxOperation();
        if (StringUtils.isNotBlank(organId)) {
            tBoxOperation.setOrganId(organId);
        }
        if (status != null) {
            tBoxOperation.setStatus(status);
        }
        if (StringUtils.isNotBlank(areaId)) {
            tBoxOperation.setAreaId(areaId);
        }
        if (StringUtils.isNotBlank(user.getAreaId())) {
            if ("4".equals(user.getType())) {
                //如果是运维账号设置数据权限
                tBoxOperation.setAreaName(getAreaId(user.getAreaId()));
            }
        }
        if (user.getRoleList().size() > 0 && !user.getRoleList().contains("1")) {
            //设置用户数据权限
            tBoxOperation.setOrganCode(user.getOrgCode());
        }
        Page<TBoxOperation> page = null;
        try {
            page = this.tBoxOperationService.selectPage(getPage(), tBoxOperation);
            //
            List<TBoxOperation> records = page.getRecords();
            fillAreaName(records);
            return getResult(page);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getFailResult();
    }


    private void fillAreaName(List<TBoxOperation> records) {
        if (CollectionUtils.isEmpty(records)) {
            return;
        }
        List<String> areaIds = records.stream().map(TBoxOperation::getAreaId).collect(Collectors.toList());
        LambdaQueryWrapper<TArea> wrapper = new QueryWrapper<TArea>().lambda()
                .select(TArea::getId, TArea::getFullName, TArea::getName)
                .in(TArea::getId, areaIds);
        List<TArea> tAreas = areaService.list(wrapper);
        //设置区域名称
        records.stream().forEach(r -> {
            Integer status = r.getStatus();
            if(status.equals(1)){
                r.setStatusString("未激活");
            }
            if(status.equals(2)){
                r.setStatusString("已激活");
            }
            if(status.equals(3)){
                r.setStatusString("故障");
            }
            tAreas.stream().forEach(a -> {
                if (r.getAreaId() != null && r.getAreaId().equals(String.valueOf(a.getId()))) {
                    //设置地区全名
                    r.setAreaName(a.getFullName());
                }
            });
        });
    }

    //机顶盒导出
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "_index", value = "分页起始偏移量", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "_size", value = "返回条数", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "organId", value = "所属单位", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "status", value = "状态 1.未激活 2.已激活 3.故障", paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "areaId", value = "区域", paramType = "query", dataType = "String")
    })
    @PostMapping("/excel/getPageList")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/getPageList")
    @ApiOperation(value = "获取机顶盒运维信息分页列表Excel导出", notes = "获取机顶盒运维信息分页列表Excel导出")
    @MethodLog(operModule = OperModule.STBOPERATION, operType = OperType.SELECT)
    public void excelPageList(String organId, Integer status, String areaId,HttpServletResponse response) {
        TUser user = getcurUser();
        TBoxOperation tBoxOperation = new TBoxOperation();
        if (StringUtils.isNotBlank(organId)) {
            tBoxOperation.setOrganId(organId);
        }
        if (status != null) {
            tBoxOperation.setStatus(status);
        }
        if (StringUtils.isNotBlank(areaId)) {
            tBoxOperation.setAreaId(areaId);
        }
        if (StringUtils.isNotBlank(user.getAreaId())) {
            if ("4".equals(user.getType())) {
                //如果是运维账号设置数据权限
                tBoxOperation.setAreaName(getAreaId(user.getAreaId()));
            }
        }
        if (user.getRoleList().size() > 0 && !user.getRoleList().contains("1")) {
            //设置用户数据权限
            tBoxOperation.setOrganCode(user.getOrgCode());
        }
        Page<TBoxOperation> page = null;
        try {
            List<TBoxOperation> records  = this.tBoxOperationService.selectListA( tBoxOperation);
            //

            fillAreaName(records);
            //导出excel
            ExcelWriter writer = ExcelUtil.getWriter();

            writer.addHeaderAlias("mac", "MAC地址");
            writer.addHeaderAlias("organName", "所属单位");
            writer.addHeaderAlias("userName","单位管理员" );
            writer.addHeaderAlias("areaName", "所属区域");
            writer.addHeaderAlias("statusString","机顶盒状态");
            //
            writer.setOnlyAlias(true);
            writer.write(records, true);
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            String name = "机顶盒运维信息";
            name = URLEncoder.encode(name, String.valueOf(StandardCharsets.UTF_8));
            response.setHeader("Content-Disposition","attachment;filename="+name+".xls");
            ServletOutputStream out= null;
            try {
                out = response.getOutputStream();
                writer.flush(out, true);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                // 关闭writer,释放内存
                writer.close();
            }
            //此处记得关闭输出Servlet流
            IoUtil.close(out);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    @ApiOperation(value = "获取机顶盒运维信息详情", notes = "获取机顶盒运维信息详情")
    @GetMapping("/getById")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/getById")
    @MethodLog(operModule = OperModule.STBOPERATION, operType = OperType.SELECT)
    public Map<String, Object> getById(String id) {
        TBoxOperation tBoxOperation = null;
        try {
            tBoxOperation = tBoxOperationService.getById(id);
            return getResult(tBoxOperation);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getFailResult();
    }


    @PostMapping("/export")
    @RequiresAuthentication  //@RequiresPermissions("/boxOperation/selectPageList")
    @ApiOperation(value = "导出机顶盒基础信息列表", notes = "导出机顶盒基础信息列表")
//    @MethodLog(operModule = OperModule.STBBASE,operType = OperType.SELECT)
    public void export(String organId, String areaId, LocalDate beginDate, LocalDate endDate, HttpServletResponse response) {
        TUser user1 = getcurUser();
        TUser user = new TUser();
        if (StringUtils.isNotBlank(organId)) {
            user.setOrgId(organId);
        }
        if (StringUtils.isNotBlank(areaId)) {
            user.setAreaId(areaId);
        }
        //设置数据权限
//        if (StringUtils.isNotBlank(user1.getAreaId())) {
//            String areaId1 = getAreaId(user1.getAreaId());
//            user.setAreaName(areaId1);
//        }
        if (beginDate != null && endDate != null) {
            user.setBeginDate(beginDate.atTime(0, 0, 0));
            user.setEndDate(endDate.atTime(23, 59, 59));
        }
        if (!user1.getRoleList().contains("1")) {
            user.setOrgCode(user1.getOrgCode());
        }
        try {
            List<TBoxOperation> list = tBoxOperationService.selectBoxList(user);
            String[] title = {"序号", "MAc地址", "所属单位", "展板播放次数", "到期时间"};
            String[] keys = {"id", "mac", "organName", "num", "macStatus"};
            HSSFWorkbook hssfWorkbook = ExportExcelUtil.getHSSFWorkbook(title, list, keys);
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + "机顶盒基础信息表.xls");
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
            OutputStream os = response.getOutputStream();
            hssfWorkbook.write(os);
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static String getAreaId(String areaId) {
        if ("0000".equals(areaId.substring(2))) {
            areaId = areaId.substring(0, 2);
        } else if ("00".equals(areaId.substring(4))) {
            areaId = areaId.substring(0, 4);
        }
        return areaId;
    }

}