package com.engine.salary.web;

import com.engine.common.util.ParamUtil;
import com.engine.common.util.ServiceUtil;
import com.engine.salary.entity.siaccount.po.InsuranceAccountInspectPO;
import com.engine.salary.entity.siarchives.param.InsuranceArchivesListParam;
import com.engine.salary.entity.siarchives.param.SIArchiveImportParam;
import com.engine.salary.entity.sischeme.dto.InsuranceSchemeListDTO;
import com.engine.salary.entity.sischeme.param.InsuranceSchemeDetailUpdateParam;
import com.engine.salary.entity.sischeme.param.InsuranceSchemeParam;
import com.engine.salary.entity.sischeme.param.InsuranceSchemeReqParam;
import com.engine.salary.enums.siaccount.EmployeeStatusEnum;
import com.engine.salary.enums.sicategory.WelfareTypeEnum;
import com.engine.salary.service.SIAccountService;
import com.engine.salary.service.SISchemeService;
import com.engine.salary.service.impl.SIAccountServiceImpl;
import com.engine.salary.service.impl.SISchemeServiceImpl;
import com.engine.salary.util.ResponseResult;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.wrapper.SISchemeWrapper;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jetbrains.annotations.NotNull;
import weaver.hrm.HrmUserVarify;
import weaver.hrm.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author weaver_cl
 * @Description: 社保方案控制器
 * @Date 2022/3/7
 * @Version V1.0
 **/
@Slf4j
public class SISchemeController {

    private SISchemeService getService(User user) {
        return ServiceUtil.getService(SISchemeServiceImpl.class, user);
    }

    private SISchemeWrapper getSISchemeWrapper(User user) {

        return ServiceUtil.getService(SISchemeWrapper.class, user);
    }

    private SIAccountService getSIAccountService(User user) {
        return ServiceUtil.getService(SIAccountServiceImpl.class, user);
    }

    /**
     * 查询福利方案表单
     *
     * @param request
     * @param response
     * @return
     */
    @GET
    @Path("/getForm")
    @Produces(MediaType.APPLICATION_JSON)
    public String getForm(@Context HttpServletRequest request, @Context HttpServletResponse response,
                          @DefaultValue("SOCIAL_SECURITY") @QueryParam(value = "welfareTypeEnum") WelfareTypeEnum welfareTypeEnum) {
        User user = HrmUserVarify.getUser(request, response);
        Map<String, Object> map = ParamUtil.request2Map(request);
        //InsuranceSchemeDTO insuranceSchemeDTO = InsuranceSchemeDTO.builder().welfareType(welfareTypeEnum).build();
        map.put("welfareTypeEnum", welfareTypeEnum);
        return new ResponseResult<Map<String, Object>, Map<String, Object>>(user).run(getService(user)::getForm, map);
    }


    /**
     * 查询福利方案列表
     *
     * @param request
     * @param response
     * @return
     */
    @POST
    @Path("/getTable")
    @Produces(MediaType.APPLICATION_JSON)
    public String list(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody InsuranceSchemeParam insuranceSchemeParam) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<InsuranceSchemeParam, PageInfo<InsuranceSchemeListDTO>>(user).run(getSISchemeWrapper(user)::listPage, insuranceSchemeParam);
    }


    /**
     * 新增
     *
     * @param request
     * @param response
     * @return
     */
    @POST
    @Path("/insert")
    @Produces(MediaType.APPLICATION_JSON)
    public String insertScheme(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody InsuranceSchemeReqParam insuranceSchemeReqParam) {
        User user = HrmUserVarify.getUser(request, response);
        Map<String, Object> map = ParamUtil.request2Map(request);
        map.put("insuranceSchemeReqParam", insuranceSchemeReqParam);
        return new ResponseResult<Map<String, Object>, Map<String, Object>>(user).run(getService(user)::insertScheme, map);
    }

    /**
     * 编辑方案主表和明细表数据
     *
     * @param request
     * @param response
     * @param insuranceSchemeReqParam
     * @return
     */
    @POST
    @Path("/update")
    @Produces(MediaType.APPLICATION_JSON)
    public String update(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody InsuranceSchemeReqParam insuranceSchemeReqParam) {
        User user = HrmUserVarify.getUser(request, response);
        Map<String, Object> map = ParamUtil.request2Map(request);
        map.put("insuranceSchemeReqParam", insuranceSchemeReqParam);
        return new ResponseResult<Map<String, Object>, Map<String, Object>>(user).run(getService(user)::update, map);
    }

    /**
     * 编辑方案明细表数据
     *
     * @param request
     * @param response
     * @param schemeDetailList
     * @return
     */
    @POST
    @Path("/updateSchemeDetail")
    @Produces(MediaType.APPLICATION_JSON)
    public String updateSchemeDetail(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody List<InsuranceSchemeDetailUpdateParam> schemeDetailList) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<List<InsuranceSchemeDetailUpdateParam>, List<String>>(user).run(getService(user)::updateSchemeDetail, schemeDetailList);
    }

    /**
     * 删除(接口中暂无)
     *
     * @param request
     * @param response
     * @param insuranceSchemeReqParam
     * @return
     */
    @POST
    @Path("/delete")
    @Produces(MediaType.APPLICATION_JSON)
    public String deleteTaxRate(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody InsuranceSchemeReqParam insuranceSchemeReqParam) {
        User user = HrmUserVarify.getUser(request, response);
        Map<String, Object> map = ParamUtil.request2Map(request);
        map.put("ids", insuranceSchemeReqParam.getIds());
        map.put("welfareTypeId", insuranceSchemeReqParam.getWelfareTypeEnum().getValue());
        return new ResponseResult<Map<String, Object>, Map<String, Object>>(user).run(getService(user)::delete, map);
    }

    /**
     * 复制福利方案表单
     *
     * @param request
     * @param response
     * @return
     */
    @GET
    @Path("/copyScheme")
    @Produces(MediaType.APPLICATION_JSON)
    public String copyScheme(@Context HttpServletRequest request, @Context HttpServletResponse response,
                             @QueryParam("id") Long id, @QueryParam("schemeName") String schemeName) {
        User user = HrmUserVarify.getUser(request, response);
        Map<String, Object> map = ParamUtil.request2Map(request);
        map.put("id", id);
        map.put("schemeName", schemeName);
        return new ResponseResult<Map<String, Object>, Map<String, Object>>(user).run(getService(user)::copyScheme, map);
    }


    /**
     * 导出档案
     *
     * @return
     */
    @GET
    @Path("/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response export(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            InsuranceArchivesListParam param = buildInsuranceArchivesListParam(request);
            User user = HrmUserVarify.getUser(request, response);
            XSSFWorkbook workbook = getService(user).export(param);
            String fileName;
            //表头
            if (param.getRunStatuses().size() > 0) {
                if (param.getRunStatuses().contains(EmployeeStatusEnum.STAY_ADD.getValue()) && param.getRunStatuses().size() == 1) {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导出" + "-" + EmployeeStatusEnum.STAY_ADD.getDefaultLabel());
                } else if (param.getRunStatuses().contains(EmployeeStatusEnum.PAYING.getValue()) && param.getRunStatuses().contains(EmployeeStatusEnum.STAY_DEL.getValue()) && param.getRunStatuses().size() == 2) {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导出" + "-" + "在缴员工");
                } else if (param.getRunStatuses().contains(EmployeeStatusEnum.STAY_DEL.getValue()) && param.getRunStatuses().size() == 1) {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导出" + "-" + EmployeeStatusEnum.STAY_DEL.getDefaultLabel());
                } else if (param.getRunStatuses().contains(EmployeeStatusEnum.STOP_PAYMENT_FROM_ADD.getValue()) && param.getRunStatuses().contains(EmployeeStatusEnum.STOP_PAYMENT_FROM_DEL.getValue()) && param.getRunStatuses().size() == 2) {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导出" + "-" + "停缴员工");
                } else {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导出");
                }
            } else {
                fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导出");
            }

            fileName = fileName + LocalDate.now();
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output)
                    .header("Content-disposition", "attachment;filename=" + fileName)
                    .header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("社保福利档案导出异常", e);
            throw e;
        }
    }


    @POST
    @Path("/preview")
    @Produces(MediaType.APPLICATION_JSON)
    public String preview(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SIArchiveImportParam queryParam) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SIArchiveImportParam, Map<String, Object>>(user).run(getService(user)::preview, queryParam);
    }


    @POST
    @Path("/importBatch")
    @Produces(MediaType.APPLICATION_JSON)
    public String batchImportEbatch(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SIArchiveImportParam queryParam) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SIArchiveImportParam, Map<String, Object>>(user).run(getService(user)::batchImportEbatch, queryParam);
    }


    /**
     * 导出档案和档案模板
     *
     * @return
     */
    @GET
    @Path("/template/export")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response exportTemplate(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            InsuranceArchivesListParam param = buildInsuranceArchivesListParam(request);

            param.setExportData(Boolean.valueOf(request.getParameter("exportData")));
            param.setExtWelArchiveList(Boolean.valueOf(request.getParameter("extWelArchiveList")));
            User user = HrmUserVarify.getUser(request, response);
            if (param.getInspectAll() != null && param.getInspectAll()) {
                List<InsuranceAccountInspectPO> insuranceAccountInspectPOS = getSIAccountService(user).allInspects(param.getIds(), param.getBillMonth());
                param.setEmployeeIds(insuranceAccountInspectPOS.stream().map(InsuranceAccountInspectPO::getEmployeeId).distinct().collect(Collectors.toList()));
            }
            XSSFWorkbook workbook = getService(user).exportTemplate(param);
            String fileName;
            //表头
            if (param.isExtWelArchiveList()) {
                fileName = SalaryI18nUtil.getI18nLabel(0, "社保福利档案导入模板") + "-" + SalaryI18nUtil.getI18nLabel(542679, "非系统人员");
            } else if (param.getRunStatuses().size() > 0) {
                if (param.getRunStatuses().contains(EmployeeStatusEnum.STAY_ADD.getValue()) && param.getRunStatuses().size() == 1) {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板" + "-" + EmployeeStatusEnum.STAY_ADD.getDefaultLabel());
                } else if (param.getRunStatuses().contains(EmployeeStatusEnum.PAYING.getValue()) && param.getRunStatuses().contains(EmployeeStatusEnum.STAY_DEL.getValue()) && param.getRunStatuses().size() == 2) {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板" + "-" + "在缴员工");
                } else if (param.getRunStatuses().contains(EmployeeStatusEnum.STAY_DEL.getValue()) && param.getRunStatuses().size() == 1) {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板" + "-" + EmployeeStatusEnum.STAY_DEL.getDefaultLabel());
                } else if (param.getRunStatuses().contains(EmployeeStatusEnum.STOP_PAYMENT_FROM_ADD.getValue()) && param.getRunStatuses().contains(EmployeeStatusEnum.STOP_PAYMENT_FROM_DEL.getValue()) && param.getRunStatuses().size() == 2) {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板" + "-" + "停缴员工");
                } else {
                    fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板");
                }
            } else {
                fileName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板");
            }


            fileName = fileName + LocalDate.now();
            try {
                fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            StreamingOutput output = outputStream -> {
                workbook.write(outputStream);
                outputStream.flush();
            };
            response.setContentType("application/octet-stream");
            return Response.ok(output)
                    .header("Content-disposition", "attachment;filename=" + fileName)
                    .header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("社保福利档案模板导出异常", e);
            throw e;
        }
    }

    @NotNull
    private InsuranceArchivesListParam buildInsuranceArchivesListParam(HttpServletRequest request) {
        InsuranceArchivesListParam param = new InsuranceArchivesListParam();

        String ids = request.getParameter("ids");
        if (StringUtils.isNotBlank(ids)) {
            param.setIds(Arrays.stream(ids.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        }

        String runStatuses = request.getParameter("runStatuses");
        if (StringUtils.isNotBlank(runStatuses)) {
            param.setRunStatuses(Arrays.stream(runStatuses.split(",")).map(String::valueOf).collect(Collectors.toList()));
        }

        String statusesStr = request.getParameter("statusesStr");
        if (StringUtils.isNotBlank(statusesStr)) {
            param.setStatuses(Arrays.stream(statusesStr.split(",")).map(String::new).collect(Collectors.toList()));
        }
        String userName = request.getParameter("username");
        if (StringUtils.isNotBlank(userName)) {
            param.setUserName(userName);
        }
        String jobNum = request.getParameter("jobNum");
        if (StringUtils.isNotBlank(jobNum)) {
            param.setJobNum(jobNum);
        }
        String taxAgentId = request.getParameter("taxAgentId");
        if (StringUtils.isNotBlank(taxAgentId)) {
            param.setTaxAgentId(Long.parseLong(taxAgentId));
        }
        String departmentIds = request.getParameter("departmentIdsStr");
        if (StringUtils.isNotBlank(departmentIds)) {
            param.setDepartmentIds(Arrays.stream(departmentIds.split(",")).map(BigDecimal::new).collect(Collectors.toList()));
        }
        String subcompanyIds = request.getParameter("subcompanyIdsStr");
        if (StringUtils.isNotBlank(subcompanyIds)) {
            param.setSubcompanyIds(Arrays.stream(subcompanyIds.split(",")).map(BigDecimal::new).collect(Collectors.toList()));
        }
        String positions = request.getParameter("positionsStr");
        if (StringUtils.isNotBlank(positions)) {
            param.setPositions(Arrays.stream(positions.split(",")).map(BigDecimal::new).collect(Collectors.toList()));
        }
        String siSchemeId = request.getParameter("siSchemeId");
        if (StringUtils.isNotBlank(siSchemeId)) {
            param.setSiSchemeId(Long.valueOf(siSchemeId));
        }
        String fundSchemeId = request.getParameter("fundSchemeId");
        if (StringUtils.isNotBlank(fundSchemeId)) {
            param.setFundSchemeId(Long.valueOf(fundSchemeId));
        }
        String otherSchemeId = request.getParameter("otherSchemeId");
        if (StringUtils.isNotBlank(otherSchemeId)) {
            param.setOtherSchemeId(Long.valueOf(otherSchemeId));
        }
        return param;
    }


}
