package com.bs.cw.controller;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;

import com.bs.cw.domain.CwAmortizeCost;
import com.bs.cw.domain.CwFinanceCash;
import com.bs.cw.service.ICwAmortizeCostService;
import com.bs.cw.service.ICwFinanceCashService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.bs.common.annotation.Log;
import com.bs.common.core.controller.BaseController;
import com.bs.common.core.domain.AjaxResult;
import com.bs.common.core.page.TableDataInfo;
import com.bs.common.enums.BusinessType;
import com.bs.common.utils.poi.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.core.lang.Validator;
import com.bs.cw.domain.CwFinanceWriteoff;
import com.bs.cw.service.ICwFinanceWriteoffService;
import javax.annotation.Resource;

/**
 * 费用核销记录Controller
 *
 * @author bs
 * @date 2024-02-07
 */
@Api(tags = "费用核销记录")
@RestController
@RequestMapping("/finance/writeoff")
public class CwFinanceWriteoffController extends BaseController {
    @Resource
    private ICwFinanceWriteoffService cwFinanceWriteoffService;
    @Resource
    private ICwAmortizeCostService cwAmortizeCostService;
    @Resource
    private ICwFinanceCashService cwFinanceCashService;
    /**
     * 分页查询费用核销记录列表
     */
    @ApiOperation("分页查询费用核销记录列表")
    @GetMapping("/pageList")
    public TableDataInfo pageList(CwFinanceWriteoff cwFinanceWriteoff) {
        startPage();
        LambdaQueryWrapper<CwFinanceWriteoff> queryWrapper = new LambdaQueryWrapper();
        condition(queryWrapper,cwFinanceWriteoff);
        List<CwFinanceWriteoff> list = cwFinanceWriteoffService.list(queryWrapper);
        return getDataTable(list);
    }

    /**
     * 查询费用核销记录列表
     */
    @ApiOperation("查询费用核销记录列表")
    @GetMapping("/list")
    public AjaxResult list(CwFinanceWriteoff cwFinanceWriteoff) {
        LambdaQueryWrapper<CwFinanceWriteoff> queryWrapper = new LambdaQueryWrapper();
        condition(queryWrapper,cwFinanceWriteoff);
        List<CwFinanceWriteoff> list = cwFinanceWriteoffService.list(queryWrapper);
        return success(list);
    }

    /**
     * 导出费用核销记录列表
     */
    @ApiOperation("导出费用核销记录列表")
    @Log(title = "费用核销记录导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, CwFinanceWriteoff cwFinanceWriteoff) {
        LambdaQueryWrapper<CwFinanceWriteoff> queryWrapper = new LambdaQueryWrapper();
        condition(queryWrapper,cwFinanceWriteoff);
        List<CwFinanceWriteoff> list = cwFinanceWriteoffService.list(queryWrapper);
        ExcelUtil<CwFinanceWriteoff> util = new ExcelUtil<CwFinanceWriteoff>(CwFinanceWriteoff. class);
        util.exportExcel(response, list, "费用核销记录数据");
    }

    /**
     * 获取费用核销记录详细信息
     */
    @ApiOperation("获取费用核销记录详细信息")
    @GetMapping(value = "/{ID}")
    public AjaxResult getInfo(@PathVariable("ID") Long ID) {
        return success(cwFinanceWriteoffService.getById(ID));
    }

    /**
     * 新增费用核销记录
     */
    @ApiOperation("新增费用核销记录")
    @Log(title = "费用核销记录新增", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody CwFinanceWriteoff cwFinanceWriteoff) {
        return toAjax(cwFinanceWriteoffService.save(cwFinanceWriteoff));
    }

    /**
     * 修改费用核销记录
     */
    @ApiOperation("修改费用核销记录")
    @Log(title = "费用核销记录修改", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody CwFinanceWriteoff cwFinanceWriteoff) {
        return toAjax(cwFinanceWriteoffService.updateById(cwFinanceWriteoff));
    }

    @ApiOperation("根据现金日记账自动核销")
    @Log(title = "根据现金日记账自动核销", businessType = BusinessType.INSERT)
    @PostMapping("/autoWriteoffByCash")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult autoWriteoffByCash(@RequestBody CwFinanceCash cwFinanceCash) {
        if (null != cwFinanceCash && null != cwFinanceCash.getId()) {
            if (null != cwFinanceCash.getCustId() && Validator.isNotEmpty(cwFinanceCash.getRpFlag()) && Validator.isNotEmpty(cwFinanceCash.getCurrencyCode())) {
                if (cwFinanceCash.getWhxAmount().compareTo(BigDecimal.ZERO) <= 0) {
                    return warn("现金日记账无可核销金额");
                }
                //.ne(CwAmortizeCost::getItemCost, CwAmortizeCost::getWriteoffCost)
                // 根据客户和支付方向、币种找到对应的费用，且费用大于已核销金额
                LambdaQueryWrapper<CwAmortizeCost> query = new LambdaQueryWrapper<CwAmortizeCost>().eq(CwAmortizeCost::getCustId, cwFinanceCash.getCustId()).eq(CwAmortizeCost::getRpFlag, cwFinanceCash.getRpFlag());
                query.eq(CwAmortizeCost::getCurrency, cwFinanceCash.getCurrencyCode());
                query.inSql(CwAmortizeCost::getId, "select id from cw_amortize_cost where item_cost > writeoff_cost");
                List<CwAmortizeCost> lsCost = cwAmortizeCostService.list(query);
                BigDecimal whxAmount = cwFinanceCash.getWhxAmount();
                if (null != lsCost && lsCost.size() > 0) {
                    // 遍历费用，修改每个费用的已核销金额和现金的已核销金额
                    for (CwAmortizeCost cost : lsCost) {
                        BigDecimal amount = cost.getItemCost().subtract(cost.getWriteoffCost());
                        if (amount.compareTo(whxAmount) <= 0) {
                            // 未核销费用小于未核销金额
                            whxAmount = whxAmount.subtract(amount);
                            cost.setWriteoffCost(cost.getItemCost());
                            //cwFinanceCash.setWhxAmount(cwFinanceCash.getWhxAmount().subtract(amount));
                            cwFinanceCash.setHxAmount(cwFinanceCash.getHxAmount().add(amount));
                            addWriteoff(cwFinanceCash, cost, amount);
                        } else {
                            // 未核销费用大于未核销金额
                            cost.setWriteoffCost(cost.getWriteoffCost().add(whxAmount));
                            //cwFinanceCash.setWhxAmount(BigDecimal.ZERO);
                            cwFinanceCash.setHxAmount(cwFinanceCash.getPaidMoney());
                            addWriteoff(cwFinanceCash, cost, whxAmount);
                            whxAmount = BigDecimal.ZERO;
                            break;
                        }
                    }
                }
            }
            return success();
        } else {
            return warn("请选择现金日记账进行核销");
        }
    }

    @ApiOperation("根据费用自动核销")
    @Log(title = "根据费用自动核销", businessType = BusinessType.INSERT)
    @PostMapping("/autoWriteoffByCost")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult autoWriteoffByCost(@RequestBody CwAmortizeCost cwAmortizeCost) {
        if (null != cwAmortizeCost && null != cwAmortizeCost.getId()) {
            if (null != cwAmortizeCost.getCustId() && Validator.isNotEmpty(cwAmortizeCost.getRpFlag()) && Validator.isNotEmpty(cwAmortizeCost.getCurrency())) {
                if (cwAmortizeCost.getWriteoffCost().compareTo(cwAmortizeCost.getItemCost()) == 0) {
                    return warn("费用无可核销金额");
                }
                //.ne(CwAmortizeCost::getItemCost, CwAmortizeCost::getWriteoffCost)
                // 根据客户和支付方向、币种找到对应的费用，且费用大于已核销金额
                LambdaQueryWrapper<CwFinanceCash> query = new LambdaQueryWrapper<CwFinanceCash>().eq(CwFinanceCash::getCustId, cwAmortizeCost.getCustId()).eq(CwFinanceCash::getRpFlag, cwAmortizeCost.getRpFlag());
                query.eq(CwFinanceCash::getCurrencyCode, cwAmortizeCost.getCurrency());
                query.gt(CwFinanceCash::getWhxAmount, "0");
                List<CwFinanceCash> lsCash = cwFinanceCashService.list(query);
                BigDecimal whxAmount = cwAmortizeCost.getItemCost().subtract(cwAmortizeCost.getWriteoffCost());
                if (null != lsCash && lsCash.size() > 0) {
                    // 遍历费用，修改每个费用的已核销金额和现金的已核销金额
                    for (CwFinanceCash cash : lsCash) {
                        BigDecimal cashAmount = cash.getWhxAmount();
                        if (cashAmount.compareTo(whxAmount) <= 0) {
                            // 现金未核销费用小于费用未核销金额
                            cwAmortizeCost.setWriteoffCost(cwAmortizeCost.getWriteoffCost().add(cashAmount));
                            //cash.setWhxAmount(BigDecimal.ZERO);
                            cash.setHxAmount(cash.getPaidMoney());
                            whxAmount = whxAmount.subtract(cash.getWhxAmount());
                            addWriteoff(cash, cwAmortizeCost, cash.getWhxAmount());
                        } else {
                            // 现金未核销费用大于费用未核销金额
                            cwAmortizeCost.setWriteoffCost(cwAmortizeCost.getItemCost());
                            cash.setHxAmount(cash.getHxAmount().add(whxAmount));
                            addWriteoff(cash, cwAmortizeCost, whxAmount);
                            whxAmount = BigDecimal.ZERO;
                            break;
                        }
                    }
                }
            }
            return success();
        } else {
            return warn("请选择费用进行核销");
        }
    }

    private CwFinanceWriteoff addWriteoff(CwFinanceCash cash, CwAmortizeCost cost, BigDecimal amount) {
        CwFinanceWriteoff writeoff = new CwFinanceWriteoff();
        writeoff.setCashId(cash.getId());
        writeoff.setAmortizeId(cost.getId());
        writeoff.setBillNo(cost.getOrderNo());
        writeoff.setBizId(cost.getOrderType() + "-" + cost.getOrderId());
        writeoff.setPaidTime(cash.getPaidTime());
        writeoff.setWoTime(new Date());
        writeoff.setPaidAmount(cash.getPaidMoney());
        writeoff.setCurrencyCode(cash.getCurrencyCode());
        writeoff.setWoAmount(amount);
        writeoff.setCustId(cash.getCustId());
        writeoff.setRpFlag(cash.getRpFlag());
        cwFinanceWriteoffService.save(writeoff);
        cwAmortizeCostService.updateById(cost);
        cash.setWhxAmount(cash.getWhxAmount().subtract(amount));
        cwFinanceCashService.updateById(cash);
        return writeoff;
    }

    @ApiOperation("根据费用取消核销")
    @Log(title = "根据费用取消核销", businessType = BusinessType.UPDATE)
    @PostMapping("/cancelWriteoffByCost")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult cancelWriteoffByCost(@RequestBody CwAmortizeCost cwAmortizeCost) {
        if (null != cwAmortizeCost && null != cwAmortizeCost.getId()) {
            List<CwFinanceWriteoff> lsWriteoff = cwFinanceWriteoffService.list(new LambdaQueryWrapper<CwFinanceWriteoff>().eq(CwFinanceWriteoff::getAmortizeId, cwAmortizeCost.getId()));
            if (null != lsWriteoff && lsWriteoff.size() > 0) {
                for (CwFinanceWriteoff writeoff : lsWriteoff) {
                    CwFinanceCash cash = cwFinanceCashService.getById(writeoff.getCashId());
                    CwAmortizeCost cost = cwAmortizeCostService.getById(writeoff.getAmortizeId());
                    cash.setHxAmount(cash.getHxAmount().subtract(writeoff.getWoAmount()));
                    cash.setWhxAmount(cash.getWhxAmount().add(writeoff.getWoAmount()));
                    cost.setWriteoffCost(cost.getWriteoffCost().subtract(writeoff.getWoAmount()));
                    cwFinanceCashService.updateById(cash);
                    cwAmortizeCostService.updateById(cost);
                    cwFinanceWriteoffService.removeById(writeoff);
                }
            }
            return success();
        } else {
            return warn("请选择费用进行反核销");
        }
    }


    @ApiOperation("根据现金日记账取消核销")
    @Log(title = "根据现金日记账取消核销", businessType = BusinessType.UPDATE)
    @PostMapping("/cancelWriteoffByCash")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult cancelWriteoffByCash(@RequestBody CwFinanceCash cwFinanceCash) {
        if (null != cwFinanceCash && null != cwFinanceCash.getId()) {
            List<CwFinanceWriteoff> lsWriteoff = cwFinanceWriteoffService.list(new LambdaQueryWrapper<CwFinanceWriteoff>().eq(CwFinanceWriteoff::getCashId, cwFinanceCash.getId()));
            if (null != lsWriteoff && lsWriteoff.size() > 0) {
                for (CwFinanceWriteoff writeoff : lsWriteoff) {
                    CwFinanceCash cash = cwFinanceCashService.getById(writeoff.getCashId());
                    CwAmortizeCost cost = cwAmortizeCostService.getById(writeoff.getAmortizeId());
                    cash.setHxAmount(cash.getHxAmount().subtract(writeoff.getWoAmount()));
                    cash.setWhxAmount(cash.getWhxAmount().add(writeoff.getWoAmount()));
                    cost.setWriteoffCost(cost.getWriteoffCost().subtract(writeoff.getWoAmount()));
                    cwFinanceCashService.updateById(cash);
                    cwAmortizeCostService.updateById(cost);
                    cwFinanceWriteoffService.removeById(writeoff);
                }
            }
            return success();
        } else {
            return warn("请选择现金日记账进行反核销");
        }
    }
    /**
     * 删除费用核销记录
     */
    @ApiOperation("删除费用核销记录")
    @Log(title = "费用核销记录删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/{IDs}")
    public AjaxResult remove(@PathVariable List<Long> IDs) {
        return toAjax(cwFinanceWriteoffService.removeBatchByIds(IDs));
    }

    /**
      * 条件设置
      */
    private void condition (LambdaQueryWrapper<CwFinanceWriteoff> queryWrapper,CwFinanceWriteoff cwFinanceWriteoff){


        //id
        if(Validator.isNotEmpty(cwFinanceWriteoff.getId())){
            queryWrapper.eq(CwFinanceWriteoff::getId,cwFinanceWriteoff.getId());
        }

        //日记账ID
        if(Validator.isNotEmpty(cwFinanceWriteoff.getCashId())){
            queryWrapper.eq(CwFinanceWriteoff::getCashId,cwFinanceWriteoff.getCashId());
        }

        //摊销ID
        if(Validator.isNotEmpty(cwFinanceWriteoff.getAmortizeId())){
            queryWrapper.eq(CwFinanceWriteoff::getAmortizeId,cwFinanceWriteoff.getAmortizeId());
        }

        //单据号
        if(Validator.isNotEmpty(cwFinanceWriteoff.getBillNo())){
            queryWrapper.eq(CwFinanceWriteoff::getBillNo,cwFinanceWriteoff.getBillNo());
        }

        //业务单据
        if(Validator.isNotEmpty(cwFinanceWriteoff.getBizId())){
            queryWrapper.eq(CwFinanceWriteoff::getBizId,cwFinanceWriteoff.getBizId());
        }

        //实收时间
        if(Validator.isNotEmpty(cwFinanceWriteoff.getPaidTime())){
            queryWrapper.eq(CwFinanceWriteoff::getPaidTime,cwFinanceWriteoff.getPaidTime());
        }

        //核销时间
        if(Validator.isNotEmpty(cwFinanceWriteoff.getWoTime())){
            queryWrapper.eq(CwFinanceWriteoff::getWoTime,cwFinanceWriteoff.getWoTime());
        }

        //实收金额
        if(Validator.isNotEmpty(cwFinanceWriteoff.getPaidAmount())){
            queryWrapper.eq(CwFinanceWriteoff::getPaidAmount,cwFinanceWriteoff.getPaidAmount());
        }

        //币别
        if(Validator.isNotEmpty(cwFinanceWriteoff.getCurrencyCode())){
            queryWrapper.eq(CwFinanceWriteoff::getCurrencyCode,cwFinanceWriteoff.getCurrencyCode());
        }

        //经办人
        if(Validator.isNotEmpty(cwFinanceWriteoff.getUserId())){
            queryWrapper.eq(CwFinanceWriteoff::getUserId,cwFinanceWriteoff.getUserId());
        }

        //核销金额
        if(Validator.isNotEmpty(cwFinanceWriteoff.getWoAmount())){
            queryWrapper.eq(CwFinanceWriteoff::getWoAmount,cwFinanceWriteoff.getWoAmount());
        }

        //汇率
        if(Validator.isNotEmpty(cwFinanceWriteoff.getExchangeRate())){
            queryWrapper.eq(CwFinanceWriteoff::getExchangeRate,cwFinanceWriteoff.getExchangeRate());
        }

        //换算后的金额
        if(Validator.isNotEmpty(cwFinanceWriteoff.getExchangeAmount())){
            queryWrapper.eq(CwFinanceWriteoff::getExchangeAmount,cwFinanceWriteoff.getExchangeAmount());
        }

        //付款方
        if(Validator.isNotEmpty(cwFinanceWriteoff.getCustId())){
            queryWrapper.eq(CwFinanceWriteoff::getCustId,cwFinanceWriteoff.getCustId());
        }

        //状态
        if(Validator.isNotEmpty(cwFinanceWriteoff.getStatus())){
            queryWrapper.eq(CwFinanceWriteoff::getStatus,cwFinanceWriteoff.getStatus());
        }

        //创建人
        if(Validator.isNotEmpty(cwFinanceWriteoff.getCreateBy())){
            queryWrapper.eq(CwFinanceWriteoff::getCreateBy,cwFinanceWriteoff.getCreateBy());
        }

        //创建时间
        if(Validator.isNotEmpty(cwFinanceWriteoff.getCreateTime())){
            queryWrapper.eq(CwFinanceWriteoff::getCreateTime,cwFinanceWriteoff.getCreateTime());
        }

        //修改人
        if(Validator.isNotEmpty(cwFinanceWriteoff.getUpdateBy())){
            queryWrapper.eq(CwFinanceWriteoff::getUpdateBy,cwFinanceWriteoff.getUpdateBy());
        }

        //修改时间
        if(Validator.isNotEmpty(cwFinanceWriteoff.getUpdateTime())){
            queryWrapper.eq(CwFinanceWriteoff::getUpdateTime,cwFinanceWriteoff.getUpdateTime());
        }

        //删除标志（0代表存在 2代表删除）
        if(Validator.isNotEmpty(cwFinanceWriteoff.getDelFlag())){
            queryWrapper.eq(CwFinanceWriteoff::getDelFlag,cwFinanceWriteoff.getDelFlag());
        }

        //备注
        if(Validator.isNotEmpty(cwFinanceWriteoff.getRemark())){
            queryWrapper.eq(CwFinanceWriteoff::getRemark,cwFinanceWriteoff.getRemark());
        }

        //租户id
        if(Validator.isNotEmpty(cwFinanceWriteoff.getTenantId())){
            queryWrapper.eq(CwFinanceWriteoff::getTenantId,cwFinanceWriteoff.getTenantId());
        }

        //应收应付类型：0应收 1应付
        if(Validator.isNotEmpty(cwFinanceWriteoff.getRpFlag())){
            queryWrapper.eq(CwFinanceWriteoff::getRpFlag,cwFinanceWriteoff.getRpFlag());
        }

        //核销凭证
        if(Validator.isNotEmpty(cwFinanceWriteoff.getWriteoffVouch())){
            queryWrapper.eq(CwFinanceWriteoff::getWriteoffVouch,cwFinanceWriteoff.getWriteoffVouch());
        }

        //报销表主键
        if(Validator.isNotEmpty(cwFinanceWriteoff.getReimburseId())){
            queryWrapper.eq(CwFinanceWriteoff::getReimburseId,cwFinanceWriteoff.getReimburseId());
        }

        }

}
