package com.datacenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.datacenter.entity.stat.StatTodayOverview;
import com.datacenter.mapper.StatTodayOverviewMapper;
import com.datacenter.service.StatTodayOverviewService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;

@Slf4j
@Service
public class StatTodayOverviewServiceImpl
        extends ServiceImpl<StatTodayOverviewMapper, StatTodayOverview>
        implements StatTodayOverviewService {

    @Override
    public void computeAndSaveBoth(LocalDate date) {
        computeAndSave(date, false);
        computeAndSave(date, true);
    }

    @Override
    public StatTodayOverview computeAndSave(LocalDate date, boolean includeInternal) {
        int ii = includeInternal ? 1 : 0;
        log.info("[TodayOverview] 开始统计 date={} includeInternal={}", date, includeInternal);

        LocalDateTime dayStart = LocalDateTime.of(date, LocalTime.MIDNIGHT);
        LocalDateTime dayEnd   = dayStart.plusDays(1);
        long startMs = dayStart.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        long endMs   = dayEnd.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

        // ---- 今日盈亏 ----
        // 实到手续费 = 毛手续费(type 19/37) - 代理返佣(type 0/1/2)，与统计表口径一致
        BigDecimal closePl     = baseMapper.sumClosePl(startMs, endMs, ii);
        BigDecimal grossFee    = baseMapper.sumGrossFee(dayStart, dayEnd, ii);
        BigDecimal rebates     = baseMapper.sumRebates(dayStart, dayEnd, ii);
        BigDecimal platformFee = grossFee.subtract(rebates);
        BigDecimal fundingFee  = baseMapper.sumNetFundingFee(dayStart, dayEnd, ii);
        BigDecimal profitLoss  = closePl.add(platformFee).add(fundingFee);

        // ---- 充值 / 提现 / 交易额 ----
        BigDecimal depositAmount  = baseMapper.sumDeposit(dayStart, dayEnd, ii);
        BigDecimal withdrawAmount = baseMapper.sumWithdraw(dayStart, dayEnd, ii);
        BigDecimal tradeVolume    = baseMapper.sumTradeVolume(startMs, endMs, ii);

        // ---- 注册 / 登录 ----
        int registerCount = baseMapper.countRegister(dayStart, dayEnd, ii);
        int loginCount    = baseMapper.countLogin(dayStart, dayEnd, ii);

        log.info("[TodayOverview] date={} ii={} closePl={} grossFee={} rebates={} netFee={} funding={} " +
                 "deposit={} withdraw={} tradeVol={} register={} login={}",
                 date, ii, closePl, grossFee, rebates, platformFee, fundingFee,
                 depositAmount, withdrawAmount, tradeVolume, registerCount, loginCount);

        StatTodayOverview entity = getByDate(date, includeInternal);
        if (entity == null) {
            entity = new StatTodayOverview();
            entity.setStatDate(date);
            entity.setIncludeInternal(ii);
        }
        entity.setProfitLoss(profitLoss);
        entity.setDepositAmount(depositAmount);
        entity.setWithdrawAmount(withdrawAmount);
        entity.setTradeVolume(tradeVolume);
        entity.setRegisterCount(registerCount);
        entity.setLoginCount(loginCount);
        entity.setUpdatedTime(LocalDateTime.now());

        saveOrUpdate(entity);
        log.info("[TodayOverview] 写入完成 id={}", entity.getId());
        return entity;
    }

    @Override
    public StatTodayOverview getByDate(LocalDate date, boolean includeInternal) {
        return getOne(new LambdaQueryWrapper<StatTodayOverview>()
                .eq(StatTodayOverview::getStatDate, date)
                .eq(StatTodayOverview::getIncludeInternal, includeInternal ? 1 : 0));
    }

    @Override
    public void backfill(int days) {
        int n = Math.min(Math.max(days, 1), 60);
        log.info("[TodayOverview] 开始回填历史数据 days={}", n);
        for (int i = 1; i <= n; i++) {
            LocalDate date = LocalDate.now().minusDays(i);
            try {
                computeAndSaveBoth(date);
            } catch (Exception e) {
                log.error("[TodayOverview] 回填失败 date={}", date, e);
            }
        }
        log.info("[TodayOverview] 历史数据回填完成 days={}", n);
    }
}
