package com.czg.service.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.constants.SystemConstants;
import com.czg.exception.CzgException;
import com.czg.product.dto.ShopVendorBillPayDTO;
import com.czg.product.dto.ShopVendorDTO;
import com.czg.product.entity.ConsPayRecord;
import com.czg.product.entity.ConsStockFlow;
import com.czg.product.entity.ShopVendor;
import com.czg.product.service.ConsPayRecordService;
import com.czg.product.service.ConsStockFlowService;
import com.czg.product.service.ShopVendorService;
import com.czg.product.vo.ShopVendorBillPayRecordVO;
import com.czg.product.vo.ShopVendorBillRecordVO;
import com.czg.product.vo.ShopVendorBillVO;
import com.czg.product.vo.ShopVendorSummaryVO;
import com.czg.sa.StpKit;
import com.czg.service.product.mapper.ConsStockFlowMapper;
import com.czg.service.product.mapper.ShopVendorMapper;
import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 供应商
 *
 * @author Tankaikai tankaikai@aliyun.com
 * @since 1.0 2025-02-20
 */
@Service
public class ShopVendorServiceImpl extends ServiceImpl<ShopVendorMapper, ShopVendor> implements ShopVendorService {
    @Resource
    private ConsStockFlowMapper consStockFlowMapper;
    @Resource
    private ConsStockFlowService consStockFlowService;
    @Resource
    private ConsPayRecordService consPayRecordService;

    private QueryWrapper buildQueryWrapper(ShopVendorDTO param) {
        QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
        if (StrUtil.isNotEmpty(param.getName())) {
            queryWrapper.like(ShopVendor::getName, param.getName());
        }
        Long shopId = StpKit.USER.getShopId(0L);
        queryWrapper.eq(ShopVendor::getShopId, shopId);
        queryWrapper.eq(ShopVendor::getIsDel, SystemConstants.OneZero.ZERO);
        queryWrapper.orderBy(ShopVendor::getSort, true);
        queryWrapper.orderBy(ShopVendor::getId, false);
        return queryWrapper;
    }

    @Override
    public Page<ShopVendorDTO> getShopVendorPage(ShopVendorDTO param) {
        QueryWrapper queryWrapper = buildQueryWrapper(param);
        return super.pageAs(PageUtil.buildPage(), queryWrapper, ShopVendorDTO.class);
    }

    @Override
    public List<ShopVendorDTO> getShopVendorList(ShopVendorDTO param) {
        QueryWrapper queryWrapper = buildQueryWrapper(param);
        return super.listAs(queryWrapper, ShopVendorDTO.class);
    }

    @Override
    public ShopVendorDTO getShopVendorById(Long id) {
        Long shopId = StpKit.USER.getShopId(0L);
        return super.getOneAs(query().eq(ShopVendor::getId, id).eq(ShopVendor::getShopId, shopId), ShopVendorDTO.class);
    }

    @Override
    public void addShopVendor(ShopVendorDTO dto) {
        Long shopId = StpKit.USER.getShopId(0L);
        boolean exists = super.exists(query().eq(ShopVendor::getName, dto.getName()).eq(ShopVendor::getShopId, shopId));
        if (exists) {
            throw new CzgException("供应商已存在");
        }
        ShopVendor entity = BeanUtil.copyProperties(dto, ShopVendor.class);
        entity.setIsDel(SystemConstants.OneZero.ZERO);
        entity.setShopId(shopId);
        super.save(entity);
        dto.setId(entity.getId());
    }

    @Override
    public void updateShopVendor(ShopVendorDTO dto) {
        Long shopId = StpKit.USER.getShopId(0L);
        dto.setShopId(shopId);
        boolean exists = super.exists(query().eq(ShopVendor::getName, dto.getName()).eq(ShopVendor::getShopId, shopId).ne(ShopVendor::getId, dto.getId()));
        if (exists) {
            throw new CzgException("供应商已存在");
        }
        ShopVendor entity = BeanUtil.copyProperties(dto, ShopVendor.class);
        super.updateById(entity);
    }

    @Override
    public void deleteShopVendor(Long id) {
        Long shopId = StpKit.USER.getShopId(0L);
        UpdateChain.of(ShopVendor.class)
                .set(ShopVendor::getIsDel, SystemConstants.OneZero.ONE)
                .eq(ShopVendor::getId, id)
                .eq(ShopVendor::getShopId, shopId)
                .update();
    }

    @Override
    public ShopVendorSummaryVO summary(Long shopId) {
        return mapper.summary(shopId);
    }

    @Override
    public Page<ShopVendorBillVO> billList(Long shopId, String key) {
        PageHelper.startPage(PageUtil.buildPageHelp());
        return PageUtil.convert(new PageInfo<>(mapper.bill(shopId, key)));
    }

    @Override
    public Page<ShopVendorBillRecordVO> billRecord(Long shopId, Integer vendorId, String key) {
        PageHelper.startPage(PageUtil.buildPageHelp());
        return PageUtil.convert(new PageInfo<>(consStockFlowMapper.selectByVendorId(shopId, vendorId, key)));
    }

    @Override
    public Boolean pay(Long shopId, ShopVendorBillPayDTO payDTO) {
        // 批量付款
        if (payDTO.getFlowIdList().size() > 1) {
            List<ConsStockFlow> stockFlows = consStockFlowMapper.selectUnPaid(shopId, payDTO.getFlowIdList());

            BigDecimal unPaidAmount = BigDecimal.ZERO;
            ArrayList<ConsPayRecord> records = new ArrayList<>();
            for (ConsStockFlow item : stockFlows) {
                unPaidAmount = unPaidAmount.add(item.getAmountPayable().subtract(item.getActualPaymentAmount()));
                item.setActualPaymentAmount(item.getAmountPayable());
                records.add(new ConsPayRecord().setShopId(shopId).setVendorId(item.getVendorId()).setType(payDTO.getType())
                        .setAmount(item.getAmountPayable().subtract(item.getActualPaymentAmount()))
                        .setFlowId(item.getId()).setUserId(StpKit.USER.getLoginIdAsLong()).setCreateTime(DateUtil.date().toLocalDateTime()));
            }

            if (unPaidAmount.compareTo(BigDecimal.ZERO) == 0) {
                throw new CzgException("此账单已付款");
            }

            if (unPaidAmount.compareTo(payDTO.getAmount()) != 0) {
                throw new CzgException("批量付款应全部付款");
            }

            consPayRecordService.getMapper().insertBatchSelective(records, 50);
            return consStockFlowService.updateBatch(stockFlows);
        }else {
            ConsStockFlow stockFlow = consStockFlowMapper.selectOneByQuery(new QueryWrapper().eq(ConsStockFlow::getShopId, shopId).eq(ConsStockFlow::getId, payDTO.getFlowIdList().getFirst()));
            if (stockFlow == null) {
                throw new CzgException("付款账单不存在");
            }

            if (stockFlow.getAmountPayable().compareTo(stockFlow.getActualPaymentAmount()) <= 0) {
                throw new CzgException("次账单已付款完成");
            }

            if (payDTO.getAmount().compareTo(stockFlow.getAmountPayable().subtract(stockFlow.getActualPaymentAmount())) > 0) {
                throw new CzgException("付款金额不应超过待付款金额");
            }

            ConsPayRecord consPayRecord = BeanUtil.copyProperties(payDTO, ConsPayRecord.class);
            consPayRecord.setShopId(shopId);
            consPayRecord.setVendorId(stockFlow.getVendorId());
            consPayRecord.setFlowId(payDTO.getFlowIdList().getFirst());
            consPayRecord.setUserId(StpKit.USER.getLoginIdAsLong());
            consPayRecordService.save(consPayRecord);
            stockFlow.setActualPaymentAmount(stockFlow.getActualPaymentAmount().add(payDTO.getAmount()));
            return consStockFlowMapper.update(stockFlow) > 0;
        }

    }

    @Override
    public Page<ShopVendorBillPayRecordVO> payRecord(Long shopId, Long flowId) {
        return consPayRecordService.getByFlowId(shopId, flowId);
    }
}
