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.liquidnet.client.admin.zhengzai.adam.service.IAdamMemberPriceAdminService;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.service.adam.constant.AdamRedisConst;
import com.liquidnet.service.adam.dto.admin.AdamMemberPriceBuildParam;
import com.liquidnet.service.adam.dto.vo.AdamMemberPriceVo;
import com.liquidnet.service.adam.entity.AdamMemberPrice;
import com.liquidnet.service.adam.mapper.AdamMemberPriceMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AdamMemberPriceAdminServiceImpl extends ServiceImpl<AdamMemberPriceMapper, AdamMemberPrice> implements IAdamMemberPriceAdminService {
    @Autowired
    private AdamMemberPriceMapper adamMemberPriceMapper;
    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;

    @Override
    @Transactional
    public AdamMemberPrice edit(AdamMemberPriceBuildParam param) {
        String memberId = param.getMemberId();
        LocalDateTime nowTime = LocalDateTime.now();
        Integer targetState = null == param.getState() ? 1 : param.getState();

        // 下线指定价格包
        if (Integer.valueOf(2).equals(targetState)) {
            if (StringUtils.isBlank(param.getMemberPriceId())) {
                throw new LiquidnetServiceException("-1", "下线价格包需指定会员价格ID");
            }
            AdamMemberPrice offline = new AdamMemberPrice();
            offline.setState(2);
            offline.setUpdatedAt(nowTime);
            boolean offlineRst = adamMemberPriceMapper.update(offline, Wrappers.lambdaUpdate(AdamMemberPrice.class)
                    .eq(AdamMemberPrice::getMemberId, memberId)
                    .eq(AdamMemberPrice::getMemberPriceId, param.getMemberPriceId())) > 0;
            if (!offlineRst) {
                throw new LiquidnetServiceException("-1", "会员价格下线失败");
            }
            refreshMemberPriceRedis(memberId);
            return adamMemberPriceMapper.selectOne(Wrappers.lambdaQuery(AdamMemberPrice.class)
                    .eq(AdamMemberPrice::getMemberId, memberId)
                    .eq(AdamMemberPrice::getMemberPriceId, param.getMemberPriceId()));
        }

        // 重新上线：只改 state，不改价格字段
        if (Integer.valueOf(1).equals(targetState)
                && StringUtils.isNotBlank(param.getMemberPriceId())
                && param.getPrice() == null
                && param.getPriceFixed() == null
                && param.getPriceSpecial() == null
                && param.getDays() == null) {
            AdamMemberPrice online = new AdamMemberPrice();
            online.setState(1);
            online.setUpdatedAt(nowTime);
            boolean onlineRst = adamMemberPriceMapper.update(online, Wrappers.lambdaUpdate(AdamMemberPrice.class)
                    .eq(AdamMemberPrice::getMemberId, memberId)
                    .eq(AdamMemberPrice::getMemberPriceId, param.getMemberPriceId())) > 0;
            if (!onlineRst) {
                throw new LiquidnetServiceException("-1", "会员价格重新上线失败");
            }
            refreshMemberPriceRedis(memberId);
            return adamMemberPriceMapper.selectOne(Wrappers.lambdaQuery(AdamMemberPrice.class)
                    .eq(AdamMemberPrice::getMemberId, memberId)
                    .eq(AdamMemberPrice::getMemberPriceId, param.getMemberPriceId()));
        }

        AdamMemberPrice saveOrUpdateInfo;
        boolean saveOrUpdateRst;
        if (StringUtils.isBlank(param.getMemberPriceId())) {
            // 新增价格包
            List<AdamMemberPrice> existList = adamMemberPriceMapper.selectList(Wrappers.lambdaQuery(AdamMemberPrice.class)
                    .eq(AdamMemberPrice::getMemberId, memberId)
                    .orderByDesc(AdamMemberPrice::getMemberPriceId));
            String nextPriceId = nextMemberPriceId(memberId, existList);

            saveOrUpdateInfo = new AdamMemberPrice();
            saveOrUpdateInfo.setMemberPriceId(nextPriceId);
            saveOrUpdateInfo.setMemberId(memberId);
            saveOrUpdateInfo.setState(1);
            saveOrUpdateInfo.setName(StringUtils.defaultIfBlank(param.getName(), ""));
            saveOrUpdateInfo.setPrice(param.getPrice());
            saveOrUpdateInfo.setPriceFixed(param.getPriceFixed());
            saveOrUpdateInfo.setPriceSpecial(param.getPriceSpecial());
            saveOrUpdateInfo.setDays(param.getDays());
            saveOrUpdateInfo.setDetail("");
            saveOrUpdateInfo.setCreatedAt(nowTime);
            saveOrUpdateRst = adamMemberPriceMapper.insert(saveOrUpdateInfo) > 0;
        } else {
            // 按 memberPriceId 更新（支持同 memberId 多价格包）
            LambdaQueryWrapper<AdamMemberPrice> byPriceId = Wrappers.lambdaQuery(AdamMemberPrice.class)
                    .eq(AdamMemberPrice::getMemberId, memberId)
                    .eq(AdamMemberPrice::getMemberPriceId, param.getMemberPriceId());
            AdamMemberPrice exists = adamMemberPriceMapper.selectOne(byPriceId);
            if (null == exists) {
                throw new LiquidnetServiceException("-1", "会员价格包不存在");
            }
            saveOrUpdateInfo = new AdamMemberPrice();
            saveOrUpdateInfo.setUpdatedAt(nowTime);
            saveOrUpdateInfo.setState(1);
            if (StringUtils.isNotBlank(param.getName())) {
                saveOrUpdateInfo.setName(param.getName());
            }
            saveOrUpdateInfo.setPrice(param.getPrice());
            saveOrUpdateInfo.setPriceFixed(param.getPriceFixed());
            saveOrUpdateInfo.setPriceSpecial(param.getPriceSpecial());
            saveOrUpdateInfo.setDays(param.getDays());
            saveOrUpdateRst = adamMemberPriceMapper.update(saveOrUpdateInfo, byPriceId) > 0;
            if (saveOrUpdateRst) {
                saveOrUpdateInfo = adamMemberPriceMapper.selectOne(byPriceId);
            }
        }

        if (saveOrUpdateRst) {
            refreshMemberPriceRedis(memberId);
            return saveOrUpdateInfo;
        }
        throw new LiquidnetServiceException("-1", "会员价格编辑失败");
    }

    private void refreshMemberPriceRedis(String memberId) {
        List<AdamMemberPrice> onlineList = adamMemberPriceMapper.selectList(Wrappers.lambdaQuery(AdamMemberPrice.class)
                .eq(AdamMemberPrice::getMemberId, memberId)
                .eq(AdamMemberPrice::getState, 1)
                .orderByAsc(AdamMemberPrice::getDays));
        List<AdamMemberPriceVo> vos = CollectionUtils.isEmpty(onlineList) ? new ArrayList<>()
                : onlineList.stream().map(p -> AdamMemberPriceVo.getNew().copy(p)).collect(Collectors.toList());
        String mpKey = AdamRedisConst.INFO_MEMBER_PRICE.concat(memberId);
        redisDataSourceUtil.getRedisAdamUtil().set(mpKey, vos);
    }

    private String nextMemberPriceId(String memberId, List<AdamMemberPrice> existList) {
        if (CollectionUtils.isEmpty(existList)) {
            return memberId + "01";
        }
        int maxSeq = 0;
        for (AdamMemberPrice price : existList) {
            String id = price.getMemberPriceId();
            if (StringUtils.isBlank(id)) {
                continue;
            }
            if (id.startsWith(memberId) && id.length() > memberId.length()) {
                String suffix = id.substring(memberId.length());
                try {
                    maxSeq = Math.max(maxSeq, Integer.parseInt(suffix));
                } catch (NumberFormatException ignore) {
                    // ignore non-numeric suffix
                }
            } else {
                try {
                    maxSeq = Math.max(maxSeq, Integer.parseInt(id));
                } catch (NumberFormatException ignore) {
                    // ignore
                }
            }
        }
        return memberId + String.format("%02d", maxSeq + 1);
    }
}
