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

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.finance.merchantreceivable.vo.PlatformCommissionPeriodSummaryVO;
import com.jeesharp.business.modules.finance.merchantsettle.enums.SettleModeEnum;
import com.jeesharp.business.modules.finance.platformrevenue.entity.PlatformRevenue;
import com.jeesharp.business.modules.finance.platformrevenue.enums.PlatformRevenuePeriodTypeEnum;
import com.jeesharp.business.modules.finance.platformrevenue.mapper.PlatformRevenueMapper;
import com.jeesharp.business.modules.finance.platformrevenue.service.PlatformRevenueService;
import com.jeesharp.business.modules.finance.platformrevenue.support.PlatformRevenueConstants;
import com.jeesharp.business.modules.finance.platformrevenue.vo.PlatformRevenueQueryVO;
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.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 平台收入日汇总领域服务实现。
 *
 * @author jeesharp
 * @since 2026-06-29
 */
@Service
@Transactional(readOnly = true)
public class PlatformRevenueServiceImpl
        extends CrudService<PlatformRevenueMapper, PlatformRevenue, PlatformRevenueQueryVO>
        implements PlatformRevenueService {

    private static final DateTimeFormatter DAY_KEY_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    @Transactional(readOnly = false)
    public void upsertDailyRollup(LocalDate statDate, String platformTenantId,
            PlatformRevenueRollupAggregateVO aggregate) {
        if (statDate == null) {
            throw new BizErrorException("统计日不能为空");
        }
        String tenantId = StrUtil.isNotBlank(platformTenantId)
                ? platformTenantId.trim()
                : PlatformRevenueConstants.DEFAULT_PLATFORM_TENANT_ID;
        PlatformRevenueRollupAggregateVO safeAggregate = normalizeAggregate(aggregate);

        PlatformRevenue existing = getBaseMapper().findByStatDateAndType(
                statDate, PlatformRevenuePeriodTypeEnum.DAY.getValue(), tenantId);
        LocalDateTime rollupTime = LocalDateTime.now();
        if (existing == null) {
            PlatformRevenue entity = new PlatformRevenue();
            entity.setStatDate(statDate);
            entity.setPeriodType(PlatformRevenuePeriodTypeEnum.DAY.getValue());
            entity.setSettleMode(SettleModeEnum.PLATFORM_COLLECT.getValue());
            applyAggregate(entity, safeAggregate);
            entity.setRollupTime(rollupTime);
            entity.setTenantId(tenantId);
            entity.setTenantCode(PlatformRevenueConstants.DEFAULT_PLATFORM_TENANT_CODE);
            entity.preInsert();
            getBaseMapper().insert(entity);
            return;
        }

        PlatformRevenue update = new PlatformRevenue();
        update.setId(existing.getId());
        applyAggregate(update, safeAggregate);
        update.setRollupTime(rollupTime);
        update.preUpdate();
        getBaseMapper().update(update);
    }

    @Override
    public List<PlatformCommissionPeriodSummaryVO> findDailyTrend(PlatformRevenueQueryVO query) {
        if (query == null) {
            return Collections.emptyList();
        }
        if (StrUtil.isBlank(query.getPeriodType())) {
            query.setPeriodType(PlatformRevenuePeriodTypeEnum.DAY.getValue());
        }
        applyDataScope(query);
        List<PlatformRevenue> rows = getBaseMapper().findDailyTrend(query);
        if (rows == null || rows.isEmpty()) {
            return Collections.emptyList();
        }
        List<PlatformCommissionPeriodSummaryVO> result = new ArrayList<>(rows.size());
        for (PlatformRevenue row : rows) {
            PlatformCommissionPeriodSummaryVO vo = new PlatformCommissionPeriodSummaryVO();
            vo.setPeriodType(PlatformRevenuePeriodTypeEnum.DAY.getValue());
            vo.setPeriodKey(row.getStatDate() != null ? row.getStatDate().format(DAY_KEY_FORMAT) : null);
            vo.setPayCount(defaultLong(row.getPayCount()));
            vo.setRefundCount(defaultLong(row.getRefundCount()));
            vo.setNetCommissionAmount(defaultAmount(row.getNetCommissionAmount()));
            vo.setNetMerchantAmount(defaultAmount(row.getNetMerchantAmount()));
            result.add(vo);
        }
        return result;
    }

    private void applyAggregate(PlatformRevenue entity, PlatformRevenueRollupAggregateVO aggregate) {
        entity.setPayCount(defaultLong(aggregate.getPayCount()));
        entity.setRefundCount(defaultLong(aggregate.getRefundCount()));
        entity.setPayBaseAmount(defaultAmount(aggregate.getPayBaseAmount()));
        entity.setRefundBaseAmount(defaultAmount(aggregate.getRefundBaseAmount()));
        entity.setNetCommissionAmount(defaultAmount(aggregate.getNetCommissionAmount()));
        entity.setNetMerchantAmount(defaultAmount(aggregate.getNetMerchantAmount()));
    }

    private PlatformRevenueRollupAggregateVO normalizeAggregate(PlatformRevenueRollupAggregateVO aggregate) {
        if (aggregate == null) {
            PlatformRevenueRollupAggregateVO empty = new PlatformRevenueRollupAggregateVO();
            empty.setPayCount(0L);
            empty.setRefundCount(0L);
            empty.setPayBaseAmount(BigDecimal.ZERO);
            empty.setRefundBaseAmount(BigDecimal.ZERO);
            empty.setNetCommissionAmount(BigDecimal.ZERO);
            empty.setNetMerchantAmount(BigDecimal.ZERO);
            return empty;
        }
        return aggregate;
    }

    private BigDecimal defaultAmount(BigDecimal value) {
        return value != null ? value : BigDecimal.ZERO;
    }

    private Long defaultLong(Long value) {
        return value != null ? value : 0L;
    }

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