package com.liquidnet.client.admin.zhengzai.adam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.liquidnet.client.admin.zhengzai.adam.service.IAdamCaomeiBadgeAdminService;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.service.adam.constant.AdamRedisConst;
import com.liquidnet.service.adam.dto.AdamCaomeiBadgeClaimCountDto;
import com.liquidnet.service.adam.dto.AdamCaomeiBadgeClaimUserDto;
import com.liquidnet.service.adam.dto.param.AdamCaomeiBadgeClaimUserSearchParam;
import com.liquidnet.service.adam.dto.param.AdamCaomeiBadgeSearchParam;
import com.liquidnet.service.adam.dto.vo.AdamCaomeiBadgeClaimUserVo;
import com.liquidnet.service.adam.dto.vo.AdamCaomeiBadgeVo;
import com.liquidnet.service.adam.entity.AdamCaomeiBadge;
import com.liquidnet.service.adam.mapper.AdamCaomeiBadgeMapper;
import com.liquidnet.service.kylin.entity.KylinPerformances;
import com.liquidnet.service.kylin.mapper.KylinPerformancesMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AdamCaomeiBadgeAdminServiceImpl extends ServiceImpl<AdamCaomeiBadgeMapper, AdamCaomeiBadge> implements IAdamCaomeiBadgeAdminService {

    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;

    @Autowired
    private KylinPerformancesMapper kylinPerformancesMapper;

    @Override
    public void delPublishedCaomeiBadges() {
        redisDataSourceUtil.getRedisAdamUtil().del(AdamRedisConst.INFO_CAOMEI_BADGE_PUBLISHED);
    }

    @Override
    public boolean save(AdamCaomeiBadge entity) {
        boolean ok = super.save(entity);
        if (ok) {
            delPublishedCaomeiBadges();
        }
        return ok;
    }

    @Override
    public boolean updateById(AdamCaomeiBadge entity) {
        boolean ok = super.updateById(entity);
        if (ok) {
            delPublishedCaomeiBadges();
        }
        return ok;
    }

    @Override
    public boolean kylinPerformanceExists(String performancesId) {
        String id = StringUtils.trimToEmpty(performancesId);
        if (StringUtils.isBlank(id)) {
            return false;
        }
        int c = kylinPerformancesMapper.selectCount(
                Wrappers.lambdaQuery(KylinPerformances.class).eq(KylinPerformances::getPerformancesId, id)
        );
        return c > 0;
    }

    @Override
    public boolean existsOtherBadgeWithSameName(String name, String excludeBadgeId) {
        String n = StringUtils.trimToEmpty(name);
        if (StringUtils.isBlank(n)) {
            return false;
        }
        LambdaQueryWrapper<AdamCaomeiBadge> w = Wrappers.lambdaQuery(AdamCaomeiBadge.class).eq(AdamCaomeiBadge::getName, n);
        if (StringUtils.isNotBlank(excludeBadgeId)) {
            w.ne(AdamCaomeiBadge::getBadgeId, excludeBadgeId.trim());
        }
        return this.count(w) > 0;
    }

    @Override
    public PageInfo<AdamCaomeiBadgeVo> listWithClaimedCount(AdamCaomeiBadgeSearchParam param) {
        LambdaQueryWrapper<AdamCaomeiBadge> queryWrapper = Wrappers.lambdaQuery(AdamCaomeiBadge.class);
        if (StringUtils.isNotBlank(param.getName())) {
            queryWrapper.like(AdamCaomeiBadge::getName, param.getName());
        }
        if (param.getType() != null) {
            queryWrapper.eq(AdamCaomeiBadge::getType, param.getType());
        }
        if (param.getDisplayStatus() != null) {
            queryWrapper.eq(AdamCaomeiBadge::getDisplayStatus, param.getDisplayStatus());
        }
        if (StringUtils.isNotBlank(param.getCreatedAtBegin())) {
            try {
                LocalDate d = LocalDate.parse(param.getCreatedAtBegin().trim());
                queryWrapper.ge(AdamCaomeiBadge::getCreatedAt, Timestamp.valueOf(d.atStartOfDay()));
            } catch (DateTimeParseException e) {
                log.warn("invalid createdAtBegin: {}", param.getCreatedAtBegin());
            }
        }
        if (StringUtils.isNotBlank(param.getCreatedAtEnd())) {
            try {
                LocalDate d = LocalDate.parse(param.getCreatedAtEnd().trim());
                queryWrapper.le(AdamCaomeiBadge::getCreatedAt, Timestamp.valueOf(d.atTime(23, 59, 59)));
            } catch (DateTimeParseException e) {
                log.warn("invalid createdAtEnd: {}", param.getCreatedAtEnd());
            }
        }
        queryWrapper.orderByDesc(AdamCaomeiBadge::getSort, AdamCaomeiBadge::getUpdatedAt);

        List<AdamCaomeiBadge> badges = this.list(queryWrapper);
        PageInfo<AdamCaomeiBadge> entityPage = new PageInfo<>(badges);

        List<String> badgeIds = entityPage.getList().stream()
                .map(AdamCaomeiBadge::getBadgeId)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());

        // key: 徽章ID，value: 领取人数
        Map<String, Integer> countMap = badgeIds.isEmpty() ? Collections.emptyMap() :
                baseMapper.selectClaimedCountByBadgeIds(badgeIds).stream()
                        .collect(Collectors.toMap(AdamCaomeiBadgeClaimCountDto::getBadgeId, AdamCaomeiBadgeClaimCountDto::getClaimedCount, (a, b) -> a));

        List<AdamCaomeiBadgeVo> voList = entityPage.getList().stream().map(item -> {
            AdamCaomeiBadgeVo vo = new AdamCaomeiBadgeVo();
            BeanUtils.copyProperties(item, vo);
            vo.setClaimedCount(countMap.getOrDefault(item.getBadgeId(), 0));
            return vo;
        }).collect(Collectors.toList());
        PageInfo<AdamCaomeiBadgeVo> voPage = new PageInfo<>(voList);
        voPage.setTotal(entityPage.getTotal());
        return voPage;
    }

    @Override
    public PageInfo<AdamCaomeiBadgeClaimUserVo> listClaimUsers(AdamCaomeiBadgeClaimUserSearchParam param) {
        if (param == null || StringUtils.isBlank(param.getBadgeId())) {
            return new PageInfo<>(Collections.emptyList());
        }
        List<AdamCaomeiBadgeClaimUserDto> list = baseMapper.selectClaimUsersByBadgeId(param.getBadgeId());
        PageInfo<AdamCaomeiBadgeClaimUserDto> dtoPage = new PageInfo<>(list);
        List<AdamCaomeiBadgeClaimUserVo> voList = dtoPage.getList().stream().map(item -> {
            AdamCaomeiBadgeClaimUserVo vo = new AdamCaomeiBadgeClaimUserVo();
            BeanUtils.copyProperties(item, vo);
            return vo;
        }).collect(Collectors.toList());
        PageInfo<AdamCaomeiBadgeClaimUserVo> voPage = new PageInfo<>(voList);
        voPage.setTotal(dtoPage.getTotal());
        return voPage;
    }
}
