package com.ruoyi.hywz.controller.stamp.tax;

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 com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.hywz.entity.*;
import com.ruoyi.hywz.entity.po.DateQueryPO;
import com.ruoyi.hywz.entity.po.IdsPO;
import com.ruoyi.hywz.entity.po.StampTaxAuditPO;
import com.ruoyi.hywz.entity.po.StampTaxComputeSavePO;
import com.ruoyi.hywz.entity.vo.stamp.tax.StampTaxBaseVo;
import com.ruoyi.hywz.service.*;
import com.ruoyi.hywz.utils.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 印花税计算 前端控制器
 * </p>
 *
 * @author mybatisplus-generator
 * @date 2024-07-14 10:07:56
 */
@RestController
@AllArgsConstructor
@RequestMapping("adsMatHyxtStampTaxComputeD")
@Api(value = "adsMatHyxtStampTaxInvoiceD", tags = "印花税项目")
public class AdsMatHyxtStampTaxComputeDController {

    private final IAdsMatHyxtStampTaxComputeDService adsMatHyxtStampTaxComputeDService;
    private final IAdsMatHyxtStampTaxComputeItemDService adsMatHyxtStampTaxComputeItemDService;
    private final IAdsMatHyxtStampTaxComputeVoucherDService adsMatHyxtStampTaxComputeVoucherDService;
    private final IAdsMatHyxtStampTaxWarningDService adsMatHyxtStampTaxWarningDService;
    private final IAdsMatHyxtStampTaxInvoiceDService adsMatHyxtStampTaxInvoiceDService;
    private final IAdsMatHyxtStampTaxContractDService adsMatHyxtStampTaxContractDService;

    @ApiOperation(value = "分页查询", notes = "分页查询")
    @PostMapping("/queryPage")
    public R queryPage(@RequestParam(defaultValue = "10") Long pageSize,
                       @RequestParam(defaultValue = "1") Long pageNo,
                       @RequestBody(required = false) AdsMatHyxtStampTaxComputeD param) {
        return adsMatHyxtStampTaxComputeDService.queryPage(pageSize, pageNo, param);
    }

    @ApiOperation(value = "查询明细", notes = "查询明细")
    @PostMapping("/getDetail")
    public R getDetail(@RequestBody AdsMatHyxtStampTaxComputeD param) {
        return R.ok(adsMatHyxtStampTaxComputeItemDService.getList(param.getId()));
    }

    @ApiOperation(value = "计算单作废", notes = "计算单作废")
    @PostMapping("/change")
    public R change(@RequestBody AdsMatHyxtStampTaxComputeD param) {
        LambdaUpdateWrapper<AdsMatHyxtStampTaxComputeD> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(AdsMatHyxtStampTaxComputeD::getId, param.getId());
        updateWrapper.set(AdsMatHyxtStampTaxComputeD::getStatus, 1);
        adsMatHyxtStampTaxComputeDService.update(updateWrapper);
        return R.ok();
    }

    @ApiOperation(value = "印花税计算单-提交审核", notes = "印花税计算单-提交审核")
    @PostMapping("/commitAudit")
    public R commitAudit(@RequestBody AdsMatHyxtStampTaxComputeD param) {
        LambdaUpdateWrapper<AdsMatHyxtStampTaxComputeD> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(AdsMatHyxtStampTaxComputeD::getId, param.getId());
        updateWrapper.set(AdsMatHyxtStampTaxComputeD::getAuditUser, param.getAuditUser());
        updateWrapper.set(AdsMatHyxtStampTaxComputeD::getAuditStatus, 1);
        adsMatHyxtStampTaxComputeDService.update(updateWrapper);
        return R.ok();
    }

    @ApiOperation(value = "印花税计算单-审核", notes = "印花税计算单-审核")
    @PostMapping("/audit")
    @Transactional(rollbackFor = Exception.class)
    public R audit(@RequestBody StampTaxAuditPO param) {
        LambdaUpdateWrapper<AdsMatHyxtStampTaxComputeD> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(AdsMatHyxtStampTaxComputeD::getId, param.getId());
        updateWrapper.set(AdsMatHyxtStampTaxComputeD::getAuditStatus, param.getAuditState());
        adsMatHyxtStampTaxComputeDService.update(updateWrapper);
        // 生成凭证
        adsMatHyxtStampTaxComputeVoucherDService.generateVoucher(param.getId());
        return R.ok();
    }

    @ApiOperation(value = "印花税计算单-撤回", notes = "印花税计算单-撤回")
    @PostMapping("/recall")
    @Transactional(rollbackFor = Exception.class)
    public R recall(@RequestBody StampTaxAuditPO param) {
        // 已审核通过无法撤回
        AdsMatHyxtStampTaxComputeD computeD = adsMatHyxtStampTaxComputeDService.getById(param.getId());
        if (ObjectUtils.isNotEmpty(computeD) && ObjectUtils.isNotEmpty(computeD.getAuditStatus())) {
            if (computeD.getAuditStatus() == 2) {
                return R.fail("已经审核通过，无法再撤回!");
            }
        }
        LambdaUpdateWrapper<AdsMatHyxtStampTaxComputeD> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(AdsMatHyxtStampTaxComputeD::getId, param.getId());
        updateWrapper.set(AdsMatHyxtStampTaxComputeD::getAuditStatus, -1);
        adsMatHyxtStampTaxComputeDService.update(updateWrapper);
        return R.ok();
    }

    @ApiOperation(value = "印花税计算单-记账凭证", notes = "印花税计算单-记账凭证")
    @PostMapping("/voucherList")
    @Transactional(rollbackFor = Exception.class)
    public R voucherList(@RequestBody StampTaxAuditPO param) {
        LambdaQueryWrapper<AdsMatHyxtStampTaxComputeVoucherD> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AdsMatHyxtStampTaxComputeVoucherD::getComputeId, param.getId());
        queryWrapper.orderByAsc(AdsMatHyxtStampTaxComputeVoucherD::getSort);
        return R.ok(adsMatHyxtStampTaxComputeVoucherDService.list(queryWrapper));
    }

    @ApiOperation(value = "印花税税基计算表", notes = "印花税税基计算表")
    @PostMapping("/stampTaxBase")
    public R stampTaxBase(@RequestBody DateQueryPO param) {
        String startDate = "null";
        String endDate = "null";
        String orgNo = param.getHomeOrgNo();
        String[] startAndEnd = DateUtil.getMonthStartAndEnd(param.getHomeDate());
        if (null != startAndEnd) {
            startDate = startAndEnd[0];
            endDate = startAndEnd[1];
        }
        List<StampTaxBaseVo> list = adsMatHyxtStampTaxComputeDService.getStampTaxBaseTable(startDate, endDate, orgNo);

        Map<String, Object> result = new HashMap<>();
        result.put("Mont", new String[] {startDate, endDate});
        result.put("list", list);
        return R.ok(result);
    }
    @ApiOperation(value = "印花税统计表", notes = "印花税统计表")
    @PostMapping("/stampTaxStatiss")
    public R stampTaxStatiss(@RequestBody DateQueryPO param) {
        String startDate = "null";
        String endDate = "null";
        String orgNo = param.getHomeOrgNo();
        String year = param.getYear();
        List<AdsMatHyxtStampTaxItemD> list = adsMatHyxtStampTaxComputeDService.getStampTaxStatiss(year, orgNo);
        sortList(list);
        List<Map<String,Object>> peps = new ArrayList<>();

        for(AdsMatHyxtStampTaxItemD adsMatHyxtStampTaxItemD : list){
            BigDecimal concatTotalNum = BigDecimal.ZERO;
            if(adsMatHyxtStampTaxItemD.getItemName().indexOf("合同")!=-1){
                concatTotalNum = concatTotalNum.add(new BigDecimal(adsMatHyxtStampTaxItemD.getTax1Fee()))
                        .add(new BigDecimal(adsMatHyxtStampTaxItemD.getTax2Fee()))
                        .add(new BigDecimal(adsMatHyxtStampTaxItemD.getTax3Fee()))
                        .add(new BigDecimal(adsMatHyxtStampTaxItemD.getTax4Fee()));
                Map<String,Object> pep = new HashMap<>();
                pep.put("value",concatTotalNum);
                pep.put("name",adsMatHyxtStampTaxItemD.getItemName());
                peps.add(pep);
            }
        }
        List<Map<String,String>> ms = new ArrayList<>();
        Map<String,String> m1 = new HashMap<>();
        Map<String,String> m2 = new HashMap<>();
        Map<String,String> m3 = new HashMap<>();
        Map<String,String> m4 = new HashMap<>();
        AdsMatHyxtStampTaxItemD adsMatHyxtStampTaxItemD1 = list.get(list.size()-1);
        m1.put("year","1季度");
        m1.put("taxFee",adsMatHyxtStampTaxItemD1.getTax1Fee());
        m1.put("tax",adsMatHyxtStampTaxItemD1.getTax1());
        m2.put("year","2季度");
        m2.put("taxFee",adsMatHyxtStampTaxItemD1.getTax2Fee());
        m2.put("tax",adsMatHyxtStampTaxItemD1.getTax2());
        m3.put("year","3季度");
        m3.put("taxFee",adsMatHyxtStampTaxItemD1.getTax3Fee());
        m3.put("tax",adsMatHyxtStampTaxItemD1.getTax3());
        m4.put("year","4季度");
        m4.put("taxFee",adsMatHyxtStampTaxItemD1.getTax4Fee());
        m4.put("tax",adsMatHyxtStampTaxItemD1.getTax4());
        ms.add(m1);
        ms.add(m2);
        ms.add(m3);
        ms.add(m4);
        Map<String, Object> result = new HashMap<>();
        result.put("Mont", new String[] {startDate, endDate});
        result.put("list", list);
        result.put("bar", ms);
        result.put("peps", peps);
        return R.ok(result);
    }
    @ApiOperation(value = "印花税计算单", notes = "印花税计算单")
    @PostMapping("/stampTaxComputeBill")
    public R stampTaxComputeBill(@RequestBody DateQueryPO param) {
        String startDate = "null";
        String endDate = "null";
        String orgNo = param.getHomeOrgNo();
        String[] startAndEnd = DateUtil.getMonthStartAndEnd(param.getHomeDate());
        if (null != startAndEnd) {
            startDate = startAndEnd[0];
            endDate = startAndEnd[1];
        }
        List<StampTaxBaseVo> list = adsMatHyxtStampTaxComputeDService.getStampTaxComputeBill(startDate, endDate, orgNo);
        Map<String, Object> result = new HashMap<>();

        result.put("Mont", new String[] {startDate, endDate});
        result.put("list", list);
        result.put("totalTaxNum", list.get(list.size()-1).getTaxNum());
        return R.ok(result);
    }

    @ApiOperation(value = "印花税计算单-导出")
    @PostMapping("/way1/stampTaxComputeBillExport")
    public void stampTaxComputeBillExport(@RequestBody StampTaxComputeSavePO param, HttpServletResponse response) throws IOException {
        InputStream fis = null;
        OutputStream ops = null;

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = java.util.UUID.randomUUID() + ".xlsx";
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        String templateFileName = "excelTemplate/stampTax/stampTaxComputeBillExport.xlsx";
        fis = Thread.currentThread().getContextClassLoader().getResourceAsStream(templateFileName);
        ops = response.getOutputStream();

        List<AdsMatHyxtStampTaxComputeItemD> itemList = param.getItemList();
        int i = 0;
        for (AdsMatHyxtStampTaxComputeItemD itemD : itemList) {
            i++;
            itemD.setNo(i);
        }

        Map<String, String> map = new HashMap<>();
        map.put("taxPayer", param.getTaxPayer());
        map.put("startDate", param.getStartDate());
        map.put("endDate", param.getEndDate());
        map.put("amount", param.getAmount());

        //填充导出信息
        ExcelWriter excelWriter = EasyExcel.write(ops, StampTaxComputeSavePO.class).withTemplate(fis).build();
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        excelWriter.fill(itemList, fillConfig, writeSheet);
        excelWriter.fill(map, fillConfig, writeSheet);
        excelWriter.finish();
    }

    @ApiOperation(value = "印花税计算表保存", notes = "印花税计算表保存")
    @PostMapping("/stampTaxComputeSave")
    public R stampTaxComputeSave(@RequestBody StampTaxComputeSavePO param) {
        // 存在预警数据，请先处理预警信息后再保存
        List<AdsMatHyxtStampTaxContractD> warnigList = adsMatHyxtStampTaxContractDService.getWarnigList(param.getHomeOrgNo());
        if (!warnigList.isEmpty()) {
            return R.fail("合同表存在预警数据，请先处理预警信息后再保存！");
        }
        return adsMatHyxtStampTaxComputeDService.stampTaxComputeSave(param);
    }

    @ApiOperation(value = "删除", notes = "删除")
    @PostMapping("/delete")
    @Transactional(rollbackFor = Exception.class)
    public R delete(@RequestBody IdsPO param) {
        LambdaQueryWrapper<AdsMatHyxtStampTaxComputeD> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AdsMatHyxtStampTaxComputeD::getId, param.getId());
        adsMatHyxtStampTaxComputeDService.remove(queryWrapper);

        LambdaQueryWrapper<AdsMatHyxtStampTaxComputeItemD> queryWrapper2 = Wrappers.lambdaQuery();
        queryWrapper2.eq(AdsMatHyxtStampTaxComputeItemD::getComputeId, param.getId());
        adsMatHyxtStampTaxComputeItemDService.remove(queryWrapper2);
        return R.ok();
    }

    public void sortList(List<AdsMatHyxtStampTaxItemD> list) {
        Collections.sort(list, new Comparator<AdsMatHyxtStampTaxItemD>() {
            @Override
            public int compare(AdsMatHyxtStampTaxItemD o1, AdsMatHyxtStampTaxItemD o2) {
                // 检查 itemName 是否为 "合计"
                boolean isO1Total = "合计".equals(o1.getItemName());
                boolean isO2Total = "合计".equals(o2.getItemName());

                if (isO1Total && !isO2Total) {
                    return 1; // o1 是 "合计"，排在后面
                } else if (!isO1Total && isO2Total) {
                    return -1; // o2 是 "合计"，排在后面
                }

                // 否则按照 tax1Fee 排序
                Double fee1 = parseTax1Fee(o1.getTax1Fee());
                Double fee2 = parseTax1Fee(o2.getTax1Fee());
                return fee2.compareTo(fee1); // 从高到低
            }

            private Double parseTax1Fee(String fee) {
                try {
                    return fee != null && !fee.isEmpty() ? Double.parseDouble(fee) : 0.0;
                } catch (NumberFormatException e) {
                    return 0.0; // 如果无法解析，返回0
                }
            }
        });
    }
}
