package com.czg.service.market.service.impl;

import cn.hutool.core.util.StrUtil;
import com.czg.account.entity.AcUserMsg;
import com.czg.account.entity.ShopInfo;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.AcUserMsgService;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService;
import com.czg.account.vo.PointsShopListVO;
import com.czg.exception.CzgException;
import com.czg.market.dto.MkPointsUserDTO;
import com.czg.market.entity.MkPointsUser;
import com.czg.market.entity.MkPointsUserRecord;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.MkPointsUserRecordService;
import com.czg.market.service.MkPointsUserService;
import com.czg.sa.StpKit;
import com.czg.service.market.mapper.MkPointsUserMapper;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 会员积分账户 服务层实现。
 *
 * @author ww
 * @since 2025-12-08
 */
@DubboService
public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkPointsUser> implements MkPointsUserService {
    @DubboReference
    private ShopInfoService shopInfoService;
    @DubboReference
    private ShopUserService shopUserService;
    @Resource
    private MkPointsUserRecordService pointsUserRecordService;

    @DubboReference
    private AcUserMsgService acUserMsgService;

    @Override
    public Page<MkPointsUserDTO> getPointsUserPage(String phone, Integer page, Integer size) {
        Long shopUserId = null;
        Long mainIdByShopId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId());
        if (StrUtil.isNotBlank(phone)) {
            ShopUser one = shopUserService.getOne(query().eq(ShopUser::getPhone, phone).eq(ShopUser::getMainShopId, mainIdByShopId));
            if (one == null) {
                return PageUtil.emptyPage();
            }
            shopUserId = one.getId();
        }
        Page<MkPointsUserDTO> pages = pageAs(Page.of(page, size), query()
                        .eq(MkPointsUser::getShopId, StpKit.USER.getShopId())
                        .eq(MkPointsUser::getShopUserId, shopUserId)
                        .orderBy(MkPointsUser::getUpdateTime, false),
                MkPointsUserDTO.class);
        pages.getRecords().forEach(s -> {
            ShopUser shopUser = shopUserService.getOne(query().eq(ShopUser::getId, s.getShopUserId()).eq(ShopUser::getMainShopId, mainIdByShopId));
            s.setHeadImg(shopUser.getHeadImg());
            s.setNickName(shopUser.getNickName());
            s.setPhone(shopUser.getPhone());
        });
        return pages;
    }

    @Override
    public List<PointsShopListVO> pointsShopList(Long userId, String shopName) {
        return listAs(query().select(MkPointsUser::getId, MkPointsUser::getShopId, MkPointsUser::getPointBalance).select(ShopInfo::getShopName, ShopInfo::getLogo, ShopInfo::getCoverImg)
                        .eq(MkPointsUser::getUserId, userId).leftJoin(ShopInfo.class).on(MkPointsUser::getShopId, ShopInfo::getId),
                PointsShopListVO.class);
    }

    @Override
    public MkPointsUser getPointsUser(Long shopId, Long shopUserId, Long userId) {
        MkPointsUser pointsUser;
        if (userId == null && shopUserId == null) {
            throw new CzgException("积分操作失败，用户ID和店铺用户ID不能同时为空");
        }
        if (shopUserId != null) {
            pointsUser = getOne(query().eq(MkPointsUser::getShopUserId, shopUserId).eq(MkPointsUser::getShopId, shopId));
            if (pointsUser == null) {
                ShopUser shopUser = shopUserService.getById(shopUserId);
                if (shopUser == null) {
                    throw new CzgException("积分操作失败，店铺用户不存在");
                }
                pointsUser = MkPointsUser.builder()
                        .userId(shopUser.getUserId())
                        .shopId(shopId)
                        .shopUserId(shopUserId)
                        .pointBalance(0L)
                        .build();
            }
        } else {
            pointsUser = getOne(query().eq(MkPointsUser::getUserId, userId).eq(MkPointsUser::getShopId, shopId));
            if (pointsUser == null) {
                ShopUser shopUser = shopUserService.getUserInfo(shopId, userId);
                if (shopUser == null) {
                    throw new CzgException("积分操作失败，店铺用户不存在");
                }
                pointsUser = MkPointsUser.builder()
                        .userId(userId)
                        .shopId(shopId)
                        .shopUserId(shopUser.getId())
                        .pointBalance(0L)
                        .build();
            }
        }
        return pointsUser;
    }

    @Override
    public Long alterPoints(Long userId, Long shopUserId, Long shopId, PointsConstant floatType, Integer points, Long sourceId, String reason) {
        if (points <= 0) {
            return null;
        }
        MkPointsUser pointsUser = getPointsUser(shopId, shopUserId, userId);
        if (floatType == null) {
            throw new CzgException("积分变动类型不能为空");
        }
        //points 取绝对值
        points = Math.abs(points);
        switch (floatType) {
            case ADD:
                pointsUser.setPointBalance(pointsUser.getPointBalance() + points);
                break;
            case SUB:
                pointsUser.setPointBalance(pointsUser.getPointBalance() - points);
                points = -points;
                break;
            default:
                throw new CzgException("不支持的积分变动类型：" + floatType);
        }
        saveOrUpdate(pointsUser);
        MkPointsUserRecord record = MkPointsUserRecord.builder()
                .mkPointsUserId(pointsUser.getId())
                .shopId(pointsUser.getShopId())
                .shopUserId(pointsUser.getShopUserId())
                .floatType(floatType.getValue())
                .floatPoints(Long.valueOf(points))
                .balancePoints(pointsUser.getPointBalance())
                .sourceId(sourceId.toString())
                .content(reason)
                .build();
        boolean save = pointsUserRecordService.save(record);
        if (!save) {
            throw new CzgException("积分操作失败，积分记录保存失败");
        }

        AcUserMsg msg = new AcUserMsg()
                .setUserId(pointsUser.getUserId())
                .setShopId(shopId)
                .setSourceId(sourceId)
                .setSourceType("order")
                .setType("points")
                .setReadStatus(0)
                .setTitle(points > 0 ? "积分到账" : "积分扣除")
                .setContent(StrUtil.format("{}提醒：{} 积分已成功{}，积分可用于兑换好物、抵扣消费，快来解锁权益！",
                        points > 0 ? "积分到账" : "积分扣除",
                        Math.abs(points),
                        points > 0 ? "存储你的账户" : "使用"));
        acUserMsgService.addUserMsg(msg);
        return record.getId();
    }

    @Override
    @Transactional
    public void removePointByOrder(Long shopId, Long userId, Long orderId, String orderNo, String reason) {
        MkPointsUser pointsUser = getPointsUser(shopId, null, userId);
        MkPointsUserRecord one = pointsUserRecordService.getOne(query()
                .eq(MkPointsUserRecord::getMkPointsUserId, pointsUser.getId())
                .eq(MkPointsUserRecord::getShopId, shopId)
                .eq(MkPointsUserRecord::getSourceId, orderId.toString())
                .eq(MkPointsUserRecord::getFloatType, PointsConstant.ADD.getValue())
                .orderBy(MkPointsUserRecord::getId, true)
        );
        if (one == null) {
            return;
        }
        Long floatPoints = Math.abs(one.getFloatPoints());
        pointsUser.setPointBalance(pointsUser.getPointBalance() - floatPoints);
        saveOrUpdate(pointsUser);

        MkPointsUserRecord record = MkPointsUserRecord.builder()
                .mkPointsUserId(pointsUser.getId())
                .shopId(pointsUser.getShopId())
                .shopUserId(pointsUser.getShopUserId())
                .floatType(PointsConstant.SUB.getValue())
                .floatPoints(-floatPoints)
                .balancePoints(pointsUser.getPointBalance())
                .sourceId(orderId.toString())
                .content(reason)
                .build();
        boolean save = pointsUserRecordService.save(record);
        if (!save) {
            throw new CzgException("积分操作失败，积分记录保存失败");
        }

        AcUserMsg msg = new AcUserMsg()
                .setUserId(pointsUser.getUserId())
                .setShopId(shopId)
                .setSourceId(orderId)
                .setSourceType("order")
                .setType("points")
                .setReadStatus(0)
                .setTitle("积分扣除")
                .setContent(StrUtil.format("订单退款积分扣除提醒：{} 积分已扣除，订单号：{}！", floatPoints, orderNo));
        acUserMsgService.addUserMsg(msg);
    }
}
