package com.jeesharp.business.modules.finance.merchantreceivable.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeesharp.business.modules.finance.merchantreceivable.entity.MerchantReceivable;
import com.jeesharp.business.modules.finance.merchantreceivable.enums.MerchantReceivableSummaryGroupByEnum;
import com.jeesharp.business.modules.finance.merchantreceivable.mapper.MerchantReceivableMapper;
import com.jeesharp.business.modules.finance.merchantreceivable.service.MerchantReceivableService;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableQueryVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableSettlementQueryVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.MerchantReceivableSettlementSummaryVO;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.PlatformCommissionPeriodSummaryVO;
import com.jeesharp.business.modules.finance.platformrevenue.vo.PlatformRevenueRollupAggregateVO;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.mybatis.core.service.CrudService;
import com.jeesharp.framework.mybatis.core.service.DataScopeWrapper;
import com.jeesharp.framework.pojo.query.PaginationVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;

/**
 * 商户应收账流水领域服务实现。
 *
 * @author jeesharp
 * @since 2026-06-11
 */
@Service
@Transactional(readOnly = true)
public class MerchantReceivableServiceImpl
        extends CrudService<MerchantReceivableMapper, MerchantReceivable, MerchantReceivableQueryVO>
        implements MerchantReceivableService {

    @Override
    public MerchantReceivable findByMallOrderIdAndEntryType(String mallOrderId, String entryType) {
        if (StrUtil.isBlank(mallOrderId) || StrUtil.isBlank(entryType)) {
            return null;
        }
        LambdaQueryWrapper<MerchantReceivable> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MerchantReceivable::getMallOrderId, mallOrderId.trim());
        wrapper.eq(MerchantReceivable::getEntryType, entryType.trim());
        wrapper.last("LIMIT 1");
        return getBaseMapper().selectOne(wrapper);
    }

    @Override
    public MerchantReceivable findByPayRefundOrderId(String payRefundOrderId) {
        if (StrUtil.isBlank(payRefundOrderId)) {
            return null;
        }
        LambdaQueryWrapper<MerchantReceivable> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MerchantReceivable::getPayRefundOrderId, payRefundOrderId.trim());
        wrapper.last("LIMIT 1");
        return getBaseMapper().selectOne(wrapper);
    }

    @Override
    public List<MerchantReceivable> findListByMallOrderId(String mallOrderId) {
        if (StrUtil.isBlank(mallOrderId)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<MerchantReceivable> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MerchantReceivable::getMallOrderId, mallOrderId.trim());
        wrapper.orderByDesc(MerchantReceivable::getBizTime);
        wrapper.orderByDesc(MerchantReceivable::getCreateDate);
        return getBaseMapper().selectList(wrapper);
    }

    @Override
    public List<MerchantReceivableSettlementSummaryVO> summarizeByMerchant(MerchantReceivableSettlementQueryVO query) {
        if (query == null) {
            return Collections.emptyList();
        }
        applyDataScope(query);
        return getBaseMapper().summarizeByMerchant(query);
    }

    @Override
    public List<PlatformCommissionPeriodSummaryVO> summarizePlatformCommissionByPeriod(
            MerchantReceivableSettlementQueryVO query) {
        if (query == null) {
            return Collections.emptyList();
        }
        query.setGroupBy(MerchantReceivableSummaryGroupByEnum.fromValue(query.getGroupBy()).getValue());
        applyDataScope(query);
        return getBaseMapper().summarizePlatformCommissionByPeriod(query);
    }

    @Override
    public PlatformRevenueRollupAggregateVO summarizeForDailyRollup(java.time.LocalDateTime windowStart,
            java.time.LocalDateTime windowEnd) {
        if (windowStart == null || windowEnd == null) {
            return emptyRollupAggregate();
        }
        PlatformRevenueRollupAggregateVO aggregate =
                getBaseMapper().summarizeForDailyRollup(windowStart, windowEnd);
        return aggregate != null ? aggregate : emptyRollupAggregate();
    }

    private PlatformRevenueRollupAggregateVO emptyRollupAggregate() {
        PlatformRevenueRollupAggregateVO vo = new PlatformRevenueRollupAggregateVO();
        vo.setPayCount(0L);
        vo.setRefundCount(0L);
        vo.setPayBaseAmount(java.math.BigDecimal.ZERO);
        vo.setRefundBaseAmount(java.math.BigDecimal.ZERO);
        vo.setNetCommissionAmount(java.math.BigDecimal.ZERO);
        vo.setNetMerchantAmount(java.math.BigDecimal.ZERO);
        return vo;
    }

    @Override
    public MerchantReceivableSettlementSummaryVO summarizeByMerchantForSettlement(String merchantTenantId,
            java.time.LocalDateTime periodStart, java.time.LocalDateTime periodEnd) {
        if (StrUtil.isBlank(merchantTenantId)) {
            return null;
        }
        return getBaseMapper().summarizeByMerchantForSettlement(merchantTenantId.trim(), periodStart, periodEnd);
    }

    @Override
    public String resolveTenantCodeByMerchantTenantId(String merchantTenantId) {
        if (StrUtil.isBlank(merchantTenantId)) {
            return null;
        }
        return getBaseMapper().selectTenantCodeByMerchantTenantId(merchantTenantId.trim());
    }

    @Override
    public List<MerchantReceivable> listUnsettledForSettlement(String merchantTenantId,
            java.time.LocalDateTime periodStart, java.time.LocalDateTime periodEnd) {
        if (StrUtil.isBlank(merchantTenantId)) {
            return Collections.emptyList();
        }
        return getBaseMapper().listUnsettledForSettlement(merchantTenantId.trim(), periodStart, periodEnd);
    }

    @Override
    @Transactional(readOnly = false)
    public void batchBindSettlementBill(List<String> receivableIds, String settlementBillId, String settlementBillNo) {
        if (receivableIds == null || receivableIds.isEmpty()) {
            return;
        }
        if (StrUtil.isBlank(settlementBillId) || StrUtil.isBlank(settlementBillNo)) {
            throw new BizErrorException("结算单信息不完整");
        }
        int updated = getBaseMapper().batchBindSettlementBill(receivableIds, settlementBillId.trim(),
                settlementBillNo.trim());
        if (updated != receivableIds.size()) {
            throw new BizErrorException("部分应收流水已被其他结算单占用，请刷新后重试");
        }
    }

    @Override
    @Transactional(readOnly = false)
    public void clearSettlementBillByBillId(String settlementBillId) {
        if (StrUtil.isBlank(settlementBillId)) {
            return;
        }
        getBaseMapper().clearSettlementBillByBillId(settlementBillId.trim());
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private void applyDataScope(PaginationVO query) {
        new DataScopeWrapper(MerchantReceivable.class, null).dataRuleFilter(query);
    }
}
