package cn.ezhizao.project.business.socialSecurity.controller;

import cn.ezhizao.common.utils.SecurityUtils;
import cn.ezhizao.common.utils.poi.ExcelUtil;
import cn.ezhizao.framework.aspectj.lang.annotation.Log;
import cn.ezhizao.framework.aspectj.lang.enums.BusinessType;
import cn.ezhizao.framework.web.controller.BaseController;
import cn.ezhizao.framework.web.domain.AjaxResult;
import cn.ezhizao.framework.web.page.TableDataInfo;
import cn.ezhizao.project.business.company.domain.BizCompany;
import cn.ezhizao.project.business.company.service.IBizCompanyService;
import cn.ezhizao.project.business.deduction.domain.BizDeduction;
import cn.ezhizao.project.business.deduction.service.IBizDeductionService;
import cn.ezhizao.project.business.entrust.domain.BizEntrust;
import cn.ezhizao.project.business.entrust.service.IBizEntrustService;
import cn.ezhizao.project.business.history.domain.BizHistory;
import cn.ezhizao.project.business.history.service.IBizHistoryService;
import cn.ezhizao.project.business.socialSecurity.domain.BizSocialSecurityConfirmDetail;
import cn.ezhizao.project.business.socialSecurity.domain.BizSocialSecurityConfirmDetailEmployee;
import cn.ezhizao.project.business.socialSecurity.domain.BizSocialSecurityDeclare;
import cn.ezhizao.project.business.socialSecurity.domain.BizSocialSecurityDeclareDetail;
import cn.ezhizao.project.business.socialSecurity.domain.vo.SocialSecurityDetailVo;
import cn.ezhizao.project.business.socialSecurity.domain.vo.SocialSecurityEmployeeExcel;
import cn.ezhizao.project.business.socialSecurity.domain.vo.SocialSecurityEmployeeVo;
import cn.ezhizao.project.business.socialSecurity.service.IBizSocialSecurityConfirmDetailEmployeeService;
import cn.ezhizao.project.business.socialSecurity.service.IBizSocialSecurityConfirmDetailService;
import cn.ezhizao.project.business.socialSecurity.service.IBizSocialSecurityDeclareDetailService;
import cn.ezhizao.project.business.socialSecurity.service.IBizSocialSecurityDeclareService;
import cn.ezhizao.project.business.workOrder.domain.BizWorkOrderRecord;
import cn.ezhizao.project.business.workOrder.service.IBizWorkOrderRecordService;
import cn.ezhizao.project.system.domain.SysFileStorage;
import cn.ezhizao.project.system.domain.SysUser;
import cn.ezhizao.project.system.mapper.SysUserMapper;
import cn.ezhizao.project.system.service.ISysFileStorageService;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * @author 周晓
 */
@RestController
@Api(tags = "FinancialSocialSecurityDeclare数据接口")
@RequestMapping(value = "/business/socialSecurityDeclare")
public class SocialSecurityDeclareController extends BaseController {

    @Resource
    IBizSocialSecurityDeclareService socialSecurityDeclareService;
    @Resource
    IBizSocialSecurityConfirmDetailService socialSecurityConfirmDetailService;
    @Resource
    IBizSocialSecurityConfirmDetailEmployeeService socialSecurityConfirmDetailEmployeeService;
    @Resource
    IBizSocialSecurityDeclareDetailService socialSecurityDeclareDetailService;
    @Resource
    IBizCompanyService companyService;
    @Resource
    SysUserMapper sysUserMapper;
    @Resource
    ISysFileStorageService fileStorageService;
    @Resource
    IBizDeductionService deductionService;
    @Resource
    IBizWorkOrderRecordService bizWorkOrderRecordService;
    @Resource
    private IBizEntrustService bizEntrustService;

    @Resource
    private IBizHistoryService bizHistoryService;
    @ApiOperation(value = "根据id查询", notes = "根据id查询")
    @GetMapping("/getById/{id}")
    @ResponseBody
    public AjaxResult getById(@PathVariable Long id) {
        return success(socialSecurityDeclareService.getById(id));
    }

    @PostMapping("/save")
    @ApiOperation(value = "保存", notes = "保存")
    @ResponseBody
    public AjaxResult save(@RequestBody BizSocialSecurityDeclare financialSocialSecurityDeclare) {
        return (financialSocialSecurityDeclare.getId() == null ? socialSecurityDeclareService.save(financialSocialSecurityDeclare) : socialSecurityDeclareService.updateById(financialSocialSecurityDeclare)) ? success() : error();
    }

    @PostMapping("/saveBatch")
    @ApiOperation(value = "批量保存", notes = "批量保存")
    @ResponseBody
    public AjaxResult saveBatch(@RequestBody List<BizSocialSecurityDeclare> list) {
        return socialSecurityDeclareService.saveOrUpdateBatch(list) ? success() : error();
    }

    @ApiOperation(value = "删除", notes = "删除")
    @GetMapping("/deleteById/{id}")
    @ResponseBody
    public AjaxResult deleteById(@PathVariable Long id) {
        return socialSecurityDeclareService.removeById(id) ? success() : error();
    }

    @ApiOperation(value = "批量删除", notes = "批量删除")
    @PostMapping("/batchDelete")
    @ResponseBody
    public AjaxResult batchDelete(@RequestBody List<Long> list) {
        return socialSecurityDeclareService.removeBatchByIds(list) ? success() : error();
    }

    @ApiOperation(value = "带条件List 分页查询", notes = "带条件List 分页查询")
    @PreAuthorize("@ss.hasPermi('business:socialSecurityDeclare:list')")
    @GetMapping("/list")
    @ResponseBody
    public TableDataInfo getList(BizSocialSecurityDeclare conditions) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(conditions);
        startPage();
        startOrderBy();
        List<BizSocialSecurityDeclare> list = socialSecurityDeclareService.getListByBean(conditions);
        if (!list.isEmpty()) {
            BizSocialSecurityDeclareDetail detailConditions = new BizSocialSecurityDeclareDetail();
            detailConditions.setYear(conditions.getYear());
            detailConditions.setMonth(conditions.getMonth());
            detailConditions.setMainIds(list.stream().map(BizSocialSecurityDeclare::getId).collect(Collectors.toList()));
//            List<BizSocialSecurityDeclareDetail> details = socialSecurityDeclareDetailService.getListByBean(detailConditions);
            List<BizSocialSecurityDeclareDetail> details = socialSecurityDeclareDetailService.getListByBean2(detailConditions);

            list.forEach(l -> {
                List<BizSocialSecurityDeclareDetail> lDetail = details.stream().filter(v -> v.getSocialSecurityDeclareId().equals(l.getId())).collect(Collectors.toList());
                l.setDetail(lDetail.isEmpty() ? null : lDetail.get(0));
            });
        }


        return getDataTable(list);
    }

    @PostMapping("/exportDetail")
    public void exportDetail(HttpServletResponse response, SocialSecurityEmployeeVo vo) throws Exception {
        OutputStream out = null;
        BufferedOutputStream bos = null;
        List<BizSocialSecurityConfirmDetailEmployee> employees = new ArrayList<>();
        List<SocialSecurityEmployeeExcel> employeeExcels = new ArrayList<>();
        try {
            ClassPathResource classPathResource = new ClassPathResource("importTemplate/社保明细模板 .xlsx");
            InputStream inputStream = classPathResource.getInputStream();
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("社保模板.xls", "utf-8");
            response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));

            out = response.getOutputStream();
            bos = new BufferedOutputStream(out);

            //读取Excel
            ExcelWriter excelWriter = EasyExcel.write(bos).withTemplate(inputStream).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();

            FillConfig fillConfig = FillConfig.builder()
                    // 开启填充换行
                    .forceNewRow(true)
                    .build();
            // 直接写入Excel数据
            List<SocialSecurityEmployeeExcel> list = getList(vo, employees, employeeExcels);
            HashMap<String, Object> map = new HashMap<>();
            BizCompany company = companyService.getById(vo.getCompanyId());
            String titleName = vo.getYear() + "年" + vo.getMonth() + "月" + company.getName() + "社保明细";
            AtomicReference<BigDecimal>[] totals = new AtomicReference[17];
            // 初始化数组
            for (int i = 0; i < totals.length; i++) {
                totals[i] = new AtomicReference<>(BigDecimal.ZERO);
            }
            // 处理列表并更新每个 AtomicReference
            list.forEach(item -> {
                totals[0].updateAndGet(v -> v.add(item.getBasePayment()));
                totals[1].updateAndGet(v -> v.add(item.getMmBasePayment()));
                totals[2].updateAndGet(v -> v.add(item.getHeatingPayment()));
                totals[3].updateAndGet(v -> v.add(item.getCompanyBirth()));
                totals[4].updateAndGet(v -> v.add(item.getCompanyLargeMedical()));
                totals[5].updateAndGet(v -> v.add(item.getCompanyMedical()));
                totals[6].updateAndGet(v -> v.add(item.getCompanyElderly()));
                totals[7].updateAndGet(v -> v.add(item.getCompanyUnemployment()));
                totals[8].updateAndGet(v -> v.add(item.getCompanyInjury()));
                totals[9].updateAndGet(v -> v.add(item.getHeatingPayment()));
                totals[10].updateAndGet(v -> v.add(item.getCompanyCount()));
                totals[11].updateAndGet(v -> v.add(item.getOneSelfLargeMedical()));
                totals[12].updateAndGet(v -> v.add(item.getOneSelfElderly()));
                totals[13].updateAndGet(v -> v.add(item.getOneSelfUnemployment()));
                totals[14].updateAndGet(v -> v.add(item.getOneSelfEMedical()));
                totals[15].updateAndGet(v -> v.add(item.getOneSelfCount()));
                totals[16].updateAndGet(v -> v.add(item.getTotalAmount()));
            });
            // 将结果放入 map 中
            map.put("titleName", titleName);
            for (int i = 0; i < totals.length; i++) {
                map.put("total" + (i + 1), totals[i].get());
            }
            excelWriter.fill(list, fillConfig, writeSheet);
            excelWriter.fill(map, fillConfig, writeSheet);
            excelWriter.finish();
            bos.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bos.close();
        }

    }

    private List<SocialSecurityEmployeeExcel> getList(SocialSecurityEmployeeVo vo, List<BizSocialSecurityConfirmDetailEmployee> employees, List<SocialSecurityEmployeeExcel> employeeExcels) {
        BizSocialSecurityConfirmDetail detail = socialSecurityConfirmDetailService
                .query().eq("company_id", vo.getCompanyId())
                .eq("year", vo.getYear())
                .eq("month", vo.getMonth())
                .eq("deleted", 0).one();

        if (detail != null) {
            employees = socialSecurityConfirmDetailEmployeeService.query()
                    .eq("social_security_confirm_detail_id", detail.getId())
                    .eq("deleted", 0)
                    .ne("change_status", 2)
                    .list();
        }
        //0.05%
        BigDecimal zeroPointZeroFiveDecimal = new BigDecimal("0.0005");
        //0.2%
        BigDecimal ZeroPointTwoDecimal = new BigDecimal("0.002");
        //0.5%
        BigDecimal halfOneDecimal = new BigDecimal("0.005");
        //1%
        BigDecimal onePercent = new BigDecimal("0.01");
        //2%
        BigDecimal twoPercent = new BigDecimal("0.02");
        //8%
        BigDecimal eightDecimal = new BigDecimal("0.08");
        //16%
        BigDecimal sixteenPercent = new BigDecimal("0.16");
        if (!CollectionUtils.isEmpty(employees)) {
            for (int i = 0; i < employees.size(); i++) {
                BizSocialSecurityConfirmDetailEmployee employee = employees.get(i);
                SocialSecurityEmployeeExcel item = new SocialSecurityEmployeeExcel();
                item.setIndex(i + 1);
                item.setName(employee.getEmployeeName());
                item.setBasePayment(employee.getCardinalNumber());
                item.setMmBasePayment(employee.getMedicalCardinalNumber());
                item.setHeatingPayment(employee.getHeatingFee());
                item.setCompanyBirth(this.multiplication(employee.getMedicalCardinalNumber(), onePercent));
                item.setCompanyLargeMedical((this.multiplication(employee.getMedicalCardinalNumber(), ZeroPointTwoDecimal)));

                item.setCompanyMedical(this.multiplication(employee.getMedicalCardinalNumber(), eightDecimal));
                item.setCompanyElderly(this.multiplication(employee.getCardinalNumber(), sixteenPercent));
                item.setCompanyUnemployment(this.multiplication(employee.getCardinalNumber(), halfOneDecimal));
                if (vo.getRadio() != null) {
                    item.setCompanyInjury(this.multiplication(employee.getCardinalNumber(), vo.getRadio().divide(BigDecimal.valueOf(100))));
                } else {
                    item.setCompanyInjury(BigDecimal.ZERO);
                }
                item.setCompanyHeat(this.multiplication(employee.getHeatingFee(), onePercent));
                item.setCompanyCount(
                        item.getCompanyBirth().add(item.getCompanyLargeMedical()).add(item.getCompanyMedical())
                                .add(item.getCompanyElderly()).add(item.getCompanyUnemployment()).add(item.getCompanyInjury()).add(item.getCompanyHeat())
                );
                item.setOneSelfLargeMedical(this.multiplication(employee.getMedicalCardinalNumber(), zeroPointZeroFiveDecimal));
                item.setOneSelfElderly(this.multiplication(employee.getCardinalNumber(), eightDecimal));
                item.setOneSelfUnemployment(this.multiplication(employee.getCardinalNumber(), halfOneDecimal));
                item.setOneSelfEMedical(this.multiplication(employee.getMedicalCardinalNumber(), twoPercent));
                item.setOneSelfCount(
                        item.getOneSelfLargeMedical().add(item.getOneSelfElderly()).add(item.getOneSelfUnemployment()).add(item.getOneSelfEMedical())
                );
                item.setTotalAmount(item.getCompanyCount().add(item.getOneSelfCount()));
                employeeExcels.add(item);
            }
        }
        return employeeExcels;
    }

    /**
     * 导出列表
     */
    @PreAuthorize("@ss.hasPermi('business:socialSecurityConfirm:export')")
    @Log(title = "个税详情", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BizSocialSecurityDeclare conditions) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(conditions);
        startOrderBy();
        List<BizSocialSecurityDeclare> list = socialSecurityDeclareService.getListByBean(conditions);
        for (BizSocialSecurityDeclare l : list) {
            l.setCurrentPeriod(conditions.getYear() + "-" + conditions.getMonth());
            BizSocialSecurityDeclareDetail detail = new BizSocialSecurityDeclareDetail();
            detail.setSocialSecurityDeclareId(l.getId());
            detail.setYear(conditions.getYear());
            detail.setMonth(conditions.getMonth());
            List<BizSocialSecurityDeclareDetail> details = socialSecurityDeclareDetailService.getListByBean(detail);
            if (details.size() == 0) {
                l.setStatusText("未开始");
                l.setMakeOut("未填写");
                l.setServiceName("");
            } else {
                detail = details.get(0);
                List<BizWorkOrderRecord> records = bizWorkOrderRecordService.query().eq("work_order_id", l.getWorkOrderId()).eq("year", conditions.getYear()).eq("month", conditions.getMonth()).eq("from_id", 0).list();
                if (records.size() > 0) {
                    SysUser sysUser = sysUserMapper.selectUserById(records.get(0).getRecorderId());
                    l.setServiceName(sysUser == null ? "" : sysUser.getNickName());
                } else {
                    l.setServiceName("");
                }
                switch (detail.getStatus()) {
                    case 0:
                        l.setStatusText("未开始");
                        l.setMakeOut("未填写");
                        break;
                    case 1:
                        l.setStatusText("进行中");
                        l.setMakeOut("进行中");
                        break;
                    case 3:
                        l.setStatusText("已完成");
                        l.setMakeOut("已填写");
                        break;
                    default:
                        break;
                }
            }
        }
        ExcelUtil<BizSocialSecurityDeclare> util = new ExcelUtil<BizSocialSecurityDeclare>(BizSocialSecurityDeclare.class);
        util.exportExcel(response, list, "社保申报任务数据");
    }


    @ApiOperation(value = "带条件List 分页查询", notes = "带条件List 分页查询")
    @PostMapping("/getListForYear")
    @ResponseBody
    public TableDataInfo getListForYear(@RequestBody BizSocialSecurityDeclare conditions) throws NoSuchFieldException, IllegalAccessException {
        setTenantId(conditions);
        List<BizSocialSecurityDeclare> list = socialSecurityDeclareService.getListByBean(conditions);
        if (!list.isEmpty()) {
            BizSocialSecurityDeclareDetail detailConditions = new BizSocialSecurityDeclareDetail();
            detailConditions.setYear(conditions.getYear());
            detailConditions.setMainIds(list.stream().map(BizSocialSecurityDeclare::getId).collect(Collectors.toList()));
            List<BizSocialSecurityDeclareDetail> details = socialSecurityDeclareDetailService.getListByBean(detailConditions);
            list.forEach(l -> {
                List<BizSocialSecurityDeclareDetail> lDetail = details.stream().filter(v -> v.getSocialSecurityDeclareId().equals(l.getId())).collect(Collectors.toList());
                l.setDetails(lDetail);
            });
        }
        return getDataTable(list);
    }


    @ApiOperation(value = "整体保存", notes = "整体保存")
    @PostMapping("/saveFile")
    @Transactional(rollbackFor = Exception.class)
    @ResponseBody
    public AjaxResult saveFile(@RequestBody SysFileStorage fileStorage) {
        boolean bool = fileStorageService.saveOrUpdate(fileStorage);
        return bool ? success(fileStorage) : error();
    }

    @PreAuthorize("@ss.hasPermi('business:socialSecurityDeclare:query')")
    @PostMapping("/getDetail")
    public AjaxResult getDetail(@RequestBody BizSocialSecurityDeclareDetail condition) {
        List<BizSocialSecurityDeclareDetail> socialSecurityConfirmDetails = socialSecurityDeclareDetailService.getListByBean(condition);
        BizCompany company = companyService.getById(condition.getCompanyId());
        int nowYear = LocalDate.now().getYear();
        int nowMonth = LocalDate.now().getMonthValue();
        String formattedMonth = String.format("%02d", nowMonth);
        String year = condition.getYear();
        String month = condition.getMonth();
        String s1 = year + month;
        String s2 = nowYear + formattedMonth;
        if (!s1.equals(s2) && socialSecurityConfirmDetails.isEmpty()) {
            return error("当前月未找到数据");
        }
        if (socialSecurityConfirmDetails.isEmpty()) {
            // 获取上个月的工资人员信息
            // 先获取之前的一个月是否已填报，然后获取填报后的工资人员信息
            BizSocialSecurityDeclareDetail detail = socialSecurityDeclareDetailService.query().eq("social_security_declare_id", condition.getSocialSecurityDeclareId()).lt("concat(year,month)", condition.getYear() + condition.getMonth()).orderByDesc("concat(year, month)").last("limit 1").one();
            if (detail != null) {
                List<SysFileStorage> files = fileStorageService.query().eq("master_table_name", "biz_social_security_declare_detail").eq("master_id", detail.getId()).eq("type", "evidenceFile").list();
                files.forEach(l -> l.setId(null));
                condition.setEvidenceFiles(files);
                List<SysFileStorage> reportFiles = fileStorageService.query().eq("master_table_name", "biz_social_security_declare_detail").eq("master_id", detail.getId()).eq("type", "reportFile").list();
                reportFiles.forEach(l -> l.setId(null));
                condition.setReportFiles(reportFiles);
                condition.setInjuryRadio(detail.getInjuryRadio());
            } else {
                condition.setEvidenceFiles(new ArrayList<>());
                condition.setReportFiles(new ArrayList<>());
            }
            condition.setCompanyName(company.getName());
            condition.setEmployeePassword(company.getEmployeePassword());
            condition.setGovernmentAccountNo(company.getGovernmentAccountNo());
            condition.setGovernmentPassword(company.getGovernmentPassword());
            condition.setSocialSecurityAccountNo(company.getSocialSecurityAccountNo());
            condition.setSocialSecurityPassword(company.getSocialSecurityPassword());
            condition.setIsFirstSocialSecurity(company.getIsFirstSocialSecurity());
            return success(condition);
        }
        Long id = condition.getSocialSecurityDeclareId();
        Long workOrderId = socialSecurityDeclareService.getById(id).getWorkOrderId();
        String s3 = year +"-"+ month+ "-01";
        BizEntrust one = bizEntrustService.getOne(new LambdaQueryWrapper<BizEntrust>()
                .eq(BizEntrust::getWorkOrderId, workOrderId)
                .eq(BizEntrust::getDeleted, 0)
                .eq(BizEntrust::getCurrentMonth, s3 ).last("limit 1"));
        BizSocialSecurityDeclareDetail bizSocialSecurityDeclareDetail = socialSecurityConfirmDetails.get(0);
        bizSocialSecurityDeclareDetail.setEntrust(one);

        return success(bizSocialSecurityDeclareDetail);
    }


    @PreAuthorize("@ss.hasPermi('business:socialSecurityDeclare:edit')")
    @ApiOperation("保存detail")
    @PostMapping("/saveDetail")
    @Log(title = "社保申报", businessType = BusinessType.UPDATE)
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult saveDetail(@RequestBody BizSocialSecurityDeclareDetail detail) {
        detail.setVerifierId(SecurityUtils.getUserId());
        detail.setVerifierTime(new Date());
        boolean bool = socialSecurityDeclareDetailService.saveOrUpdate(detail);
        bool = bool && checkDeduction(detail);
        List<SysFileStorage> fileStorages = detail.getEvidenceFiles();
        List<SysFileStorage> reportFiles = detail.getReportFiles();
        fileStorages.forEach(l -> {
            l.setMasterId(detail.getId());
            l.setMasterTableName("biz_social_security_declare_detail");
            l.setType("evidenceFile");
        });
        reportFiles.forEach(l -> {
            l.setMasterId(detail.getId());
            l.setMasterTableName("biz_social_security_declare_detail");
            l.setType("reportFile");
        });
        SysFileStorage delCondition = new SysFileStorage();
        delCondition.setMasterId(detail.getId());
        delCondition.setMasterTableName("biz_social_security_declare_detail");
        fileStorageService.physicalDelete(delCondition);
        BizHistory bizHistory = new BizHistory();
        bizHistory.setTableName("biz_social_security_declare");
        bizHistory.setCompanyId(detail.getCompanyId());
        bizHistory.setEvent("保存");
        bizHistory.setTenantId(getTenantId());
        bizHistory.setBelongPeriod(detail.getYear() + "-" +String.format("%02d", Integer.valueOf(detail.getMonth())));
        bizHistoryService.save(bizHistory);
        bool = bool && (reportFiles.isEmpty() || fileStorageService.saveOrUpdateBatch(reportFiles)) && (fileStorages.isEmpty() || fileStorageService.saveOrUpdateBatch(fileStorages)) && addRecord(detail.getSocialSecurityDeclareId(), detail.getYear(), detail.getMonth(), SecurityUtils.getUserId(), detail.getAmount().compareTo(BigDecimal.ZERO) > 0 ? "社保申报保存" : "社保申报完成", detail.getAmount().compareTo(BigDecimal.ZERO) > 0 ? 1 : 3);
        return bool ? success(detail) : error();
    }

    @ApiOperation("审核")
    @PostMapping("/verify")
    @Transactional(rollbackFor = Exception.class)
    @ResponseBody
    public AjaxResult verify(@RequestBody BizSocialSecurityDeclareDetail detail) {
//        if(detail.getValueAddedTax())
        BigDecimal amount = detail.getUnitInjury().add(detail.getUnitMedical()).add(detail.getIndividualMedical()).add(detail.getUnitPension()).add(detail.getUnitProcreate()).add(detail.getUnitUnemployment()).add(detail.getUnitSeriousIllness()).add(detail.getIndividualUnemployment()).add(detail.getIndividualSeriousIllness()).add(detail.getIndividualPension());
        BizSocialSecurityDeclare main = socialSecurityDeclareService.getById(detail.getSocialSecurityDeclareId());
        boolean res1 = true;
        if (amount.compareTo(BigDecimal.ZERO) > 0 && detail.getStatus().equals(3)) {
            BizDeduction deduction = new BizDeduction();
            deduction.setWorkOrderId(main.getWorkOrderId());
            deduction.setSourceName("社保");
            deduction.setSourceTableName("biz_social_security_declare_detail");
            deduction.setAmount(amount);
            deduction.setMonth(detail.getMonth());
            deduction.setYear(detail.getYear());
            deduction.setSourceId(detail.getId());
            deduction.setCompanyId(detail.getCompanyId());
            deduction.setDeductible(1);
            res1 = deductionService.save(deduction);
        }
        boolean res2 = socialSecurityDeclareDetailService.updateById(detail);
        return (res1 && res2) ? success() : error();
    }


    private Boolean checkDeduction(BizSocialSecurityDeclareDetail detail) {
        BizSocialSecurityDeclare bizSocialSecurityDeclare = socialSecurityDeclareService.getById(detail.getSocialSecurityDeclareId());
        if (detail.getAmount() != null && detail.getAmount().compareTo(BigDecimal.ZERO) > 0 && detail.getStatus().equals(3)) {
            BizDeduction deduction = new BizDeduction();
            deduction.setSourceName("社保");
            deduction.setWorkOrderId(bizSocialSecurityDeclare.getWorkOrderId());
            deduction.setSourceTableName("biz_social_security_declare_detail");
            deduction.setAmount(detail.getAmount());
            deduction.setMonth(detail.getMonth());
            deduction.setYear(detail.getYear());
            deduction.setSourceId(detail.getId());
            deduction.setDeductible(1);
            deduction.setCompanyId(detail.getCompanyId());
            BizCompany company = companyService.getById(detail.getCompanyId());
            deduction.setTenantId(company.getTenantId());
            return deductionService.save(deduction);
        }
        return true;
    }

    @PreAuthorize("@ss.hasPermi('business:socialSecurityDeclare:query')")
    @ApiOperation("获取社保人员信息")
    @PostMapping("/getMembers")
    @ResponseBody
    public AjaxResult getMembers(@RequestBody BizSocialSecurityConfirmDetail detail) {
        BizSocialSecurityConfirmDetail financialSocialSecurityConfirmDetail = socialSecurityConfirmDetailService.query().eq("company_id", detail.getCompanyId()).eq("year", detail.getYear()).eq("month", detail.getMonth()).one();
        if (financialSocialSecurityConfirmDetail != null) {
            List<BizSocialSecurityConfirmDetailEmployee> employees = socialSecurityConfirmDetailEmployeeService.query()
                    .eq("social_security_confirm_detail_id", financialSocialSecurityConfirmDetail.getId())
                    .list();
            return success(employees);
        } else {
            return success(new ArrayList<>());
        }
    }

    @PreAuthorize("@ss.hasPermi('business:socialSecurityDeclare:query')")
    @ApiOperation("获取社保人员信息")
    @PostMapping("/getMembersNoDelete")
    @ResponseBody
    public AjaxResult getMembersNoDelete(@RequestBody BizSocialSecurityConfirmDetail detail) {
        BizSocialSecurityConfirmDetail financialSocialSecurityConfirmDetail = socialSecurityConfirmDetailService.query().eq("company_id", detail.getCompanyId()).eq("year", detail.getYear()).eq("month", detail.getMonth()).one();
        if (financialSocialSecurityConfirmDetail != null) {
            List<BizSocialSecurityConfirmDetailEmployee> employees = socialSecurityConfirmDetailEmployeeService.query()
                    .eq("social_security_confirm_detail_id", financialSocialSecurityConfirmDetail.getId())
                    .ne("change_status", 2)
                    .list();
            return success(employees);
        } else {
            return success(new ArrayList<>());
        }
    }

    @ApiOperation("获取社保人员信息")
    @PostMapping("/getTableDetail")
    @ResponseBody
    public AjaxResult getTableDetail(@RequestBody BizSocialSecurityConfirmDetail detail) {
        ArrayList<SocialSecurityDetailVo> vos = new ArrayList<>();
        BizSocialSecurityConfirmDetail financialSocialSecurityConfirmDetail = socialSecurityConfirmDetailService.query().eq("company_id", detail.getCompanyId()).eq("year", detail.getYear()).eq("month", detail.getMonth()).one();
        if (financialSocialSecurityConfirmDetail != null) {
            List<BizSocialSecurityConfirmDetailEmployee> employees = socialSecurityConfirmDetailEmployeeService.query()
                    .eq("social_security_confirm_detail_id", financialSocialSecurityConfirmDetail.getId())
                    .ne("change_status", 2)
                    .list();
            //0.05%
            BigDecimal zeroPointZeroFiveDecimal = new BigDecimal("0.0005");
            //0.2%
            BigDecimal ZeroPointTwoDecimal = new BigDecimal("0.002");
            //0.5%
            BigDecimal halfOneDecimal = new BigDecimal("0.005");
            //1%
            BigDecimal onePercent = new BigDecimal("0.01");
            //2%
            BigDecimal twoPercent = new BigDecimal("0.02");
            //8%
            BigDecimal eightDecimal = new BigDecimal("0.08");
            //16%
            BigDecimal sixteenPercent = new BigDecimal("0.16");
            for (BizSocialSecurityConfirmDetailEmployee employee : employees) {
                SocialSecurityDetailVo vo = new SocialSecurityDetailVo();
                vo.setName(employee.getEmployeeName());
                vo.setBasePayment(employee.getCardinalNumber());
                //医疗、生育缴费基数
                vo.setMmBasePayment(employee.getMedicalCardinalNumber());
                vo.setHeatingPayment(employee.getHeatingFee());

                vo.setCompanyBirth(this.multiplication(employee.getMedicalCardinalNumber(), onePercent));
                vo.setCompanyLargeMedical(this.multiplication(employee.getMedicalCardinalNumber(), ZeroPointTwoDecimal));
                vo.setCompanyMedical(this.multiplication(employee.getMedicalCardinalNumber(), eightDecimal));
                vo.setCompanyElderly(this.multiplication(employee.getCardinalNumber(), sixteenPercent));
                vo.setCompanyUnemployment(this.multiplication(employee.getCardinalNumber(), halfOneDecimal));
                if (detail.getInjuryRadio() != null) {
                    vo.setCompanyInjury(this.multiplication(employee.getCardinalNumber(), detail.getInjuryRadio().divide(BigDecimal.valueOf(100))));
                } else {
                    vo.setCompanyInjury(BigDecimal.ZERO);
                }
                vo.setCompanyHeat(this.multiplication(employee.getHeatingFee(), onePercent));
                vo.setCompanyCount(
                        vo.getCompanyBirth().add(vo.getCompanyLargeMedical()).add(vo.getCompanyMedical())
                                .add(vo.getCompanyElderly()).add(vo.getCompanyUnemployment()).add(vo.getCompanyInjury()).add(vo.getCompanyHeat())
                );
                vo.setOneSelfLargeMedical(this.multiplication(employee.getMedicalCardinalNumber(), zeroPointZeroFiveDecimal));
                vo.setOneSelfElderly(this.multiplication(employee.getCardinalNumber(), eightDecimal));
                vo.setOneSelfUnemployment(this.multiplication(employee.getCardinalNumber(), halfOneDecimal));
                vo.setOneSelfEMedical(this.multiplication(employee.getMedicalCardinalNumber(), twoPercent));
                vo.setOneSelfCount(
                        vo.getOneSelfLargeMedical().add(vo.getOneSelfElderly()).add(vo.getOneSelfUnemployment()).add(vo.getOneSelfEMedical())
                );
                vo.setTotalAmount(vo.getCompanyCount().add(vo.getOneSelfCount()));
                vos.add(vo);
            }
            return success(vos);
        } else {
            return success(new ArrayList<>());
        }
    }

    public BigDecimal multiplication(BigDecimal a, BigDecimal b) {

        return a.multiply(b).setScale(2, BigDecimal.ROUND_HALF_UP);
    }


    @PreAuthorize("@ss.hasPermi('business:socialSecurityDeclare:return')")
    @ApiOperation("退回")
    @PostMapping("/turnBackDetail")
    @Transactional(rollbackFor = Exception.class)
    @ResponseBody
    @Log(title = "社保申报-退回", businessType = BusinessType.UPDATE)
    public AjaxResult deductionTurnBack(@RequestBody BizSocialSecurityDeclareDetail detail) {
        detail.setStatus(1);
        List<BizDeduction> deductions = deductionService.query().eq("source_table_name", "biz_social_security_declare_detail").eq("source_id", detail.getId()).list();
        if (deductions.stream().anyMatch(v -> v.getStatus().equals(2))) {
            return error("该社保记录已扣款");
        }
        deductionService.removeBatchByIds(deductions.stream().map(BizDeduction::getId).collect(Collectors.toList()));
        BizHistory bizHistory = new BizHistory();
        bizHistory.setTableName("biz_social_security_declare");
        bizHistory.setCompanyId(detail.getCompanyId());
        bizHistory.setEvent("退回");
        bizHistory.setReason(detail.getRefuseReason());
        bizHistory.setTenantId(getTenantId());
        bizHistory.setBelongPeriod(detail.getYear() + "-" +String.format("%02d", Integer.valueOf(detail.getMonth())));
        bizHistoryService.save(bizHistory);
        return socialSecurityDeclareDetailService.updateById(detail) && addRecord(detail.getSocialSecurityDeclareId(), detail.getYear(), detail.getMonth(), SecurityUtils.getUserId(), "社保申报退回", 1) ? success() : error();
    }


    private boolean addRecord(Long mainId, String year, String month, Long recorderId, String description, Integer status) {
        // 没拆分合同单价
        BizSocialSecurityDeclare socialSecurityDeclare = socialSecurityDeclareService.getById(mainId);
        Long workOrderId = socialSecurityDeclare.getWorkOrderId();
        List<BizWorkOrderRecord> records = bizWorkOrderRecordService.query().eq("work_order_id", workOrderId).eq("year", year).eq("month", month).eq("from_id", 0).list();
        if (records.isEmpty()) {
            // 新增一条记录
            BizWorkOrderRecord record = new BizWorkOrderRecord();
            record.setMonth(month);
            record.setCompanyId(socialSecurityDeclare.getCompanyId());
            record.setYear(year);
            record.setTenantId(getTenantId());
            record.setWorkOrderId(workOrderId);
            record.setStatus(status);
            record.setStatusDescript(description);
            record.setRecorderId(recorderId);
            return bizWorkOrderRecordService.save(record);
        } else {
            // 新增一条子记录
            Long fromId = records.get(0).getId();
            BizWorkOrderRecord fromRecord = records.get(0);
            BizWorkOrderRecord record = new BizWorkOrderRecord();
            record.setFromId(fromId);
            record.setMonth(fromRecord.getMonth());
            record.setCompanyId(socialSecurityDeclare.getCompanyId());
            record.setYear(fromRecord.getYear());
            record.setTenantId(fromRecord.getTenantId());
            record.setWorkOrderId(fromRecord.getWorkOrderId());
            record.setStatus(fromRecord.getStatus());
            record.setStatusDescript(fromRecord.getStatusDescript());
            record.setRecorderId(fromRecord.getRecorderId());

            fromRecord.setMonth(month);
            fromRecord.setYear(year);
            fromRecord.setCompanyId(socialSecurityDeclare.getCompanyId());
            fromRecord.setTenantId(getTenantId());
            fromRecord.setWorkOrderId(workOrderId);
            fromRecord.setStatus(status);
            fromRecord.setStatusDescript(description);
            fromRecord.setRecorderId(recorderId);
            return bizWorkOrderRecordService.save(record) &&
                    bizWorkOrderRecordService.updateById(fromRecord);
        }
    }
}
