package com.gxwebsoft.shop.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.dto.UserCardStats;
import com.gxwebsoft.shop.entity.ShopGift;
import com.gxwebsoft.shop.entity.ShopUserCoupon;
import com.gxwebsoft.shop.mapper.UserCardStatsMapper;
import com.gxwebsoft.shop.service.ShopGiftService;
import com.gxwebsoft.shop.service.ShopUserCouponService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Tag(name = "用户卡包")
@RestController
@RequestMapping("/api/user/card")
public class UserCardController extends BaseController {

    private static final long USER_CARD_STATS_CACHE_SECONDS = 60L;
    private static final DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Resource
    private RedisUtil redisUtil;
    @Resource
    private UserCardStatsMapper userCardStatsMapper;
    @Resource
    private ShopUserCouponService shopUserCouponService;
    @Resource
    private ShopGiftService shopGiftService;

    @Operation(summary = "获取当前用户卡包统计（余额/积分/优惠券/礼品卡，60s 缓存）")
    @GetMapping("/stats")
    public ApiResult<UserCardStats> getUserCardStats() {
        Integer userId = getLoginUserId();
        if (userId == null) {
            return fail("请先登录", null);
        }

        String cacheKey = "UserCard:Stats:"
            + (getTenantId() == null ? "0" : getTenantId())
            + ":" + userId;
        UserCardStats cached = redisUtil.get(cacheKey, UserCardStats.class);
        if (cached != null) {
            return success("ok", cached);
        }

        // 余额/积分：从 core 库取（避免 modules 库不存在 sys_user 导致报错）；优惠券/礼品卡用 COUNT 聚合
        Integer tenantId = getTenantId();
        Map<String, Object> bp = userCardStatsMapper.selectBalancePoints(userId, tenantId);
        BigDecimal balance = toBigDecimal(bp == null ? null : bp.get("balance"));
        Integer points = toIntObj(bp == null ? null : bp.get("points"));

        long coupons = shopUserCouponService.count(new LambdaQueryWrapper<ShopUserCoupon>()
            .eq(ShopUserCoupon::getUserId, userId)
            .eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_UNUSED));

        long giftCards = shopGiftService.count(new LambdaQueryWrapper<ShopGift>()
            .eq(ShopGift::getUserId, userId)
            .eq(ShopGift::getStatus, 0));

        UserCardStats stats = new UserCardStats();
        stats.setBalance(balance.setScale(2, RoundingMode.HALF_UP).toPlainString());
        stats.setPoints(points);
        stats.setCoupons(toInt(coupons));
        stats.setGiftCards(toInt(giftCards));
        stats.setLastUpdateTime(LocalDateTime.now().format(DATETIME_FMT));

        redisUtil.set(cacheKey, stats, USER_CARD_STATS_CACHE_SECONDS, TimeUnit.SECONDS);
        return success("ok", stats);
    }

    private static BigDecimal toBigDecimal(Object value) {
        if (value == null) {
            return BigDecimal.ZERO;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        if (value instanceof Number) {
            return BigDecimal.valueOf(((Number) value).doubleValue());
        }
        try {
            return new BigDecimal(String.valueOf(value));
        } catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }

    private static Integer toIntObj(Object value) {
        if (value == null) {
            return 0;
        }
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        try {
            return Integer.parseInt(String.valueOf(value));
        } catch (Exception e) {
            return 0;
        }
    }

    private static Integer toInt(long value) {
        if (value <= 0) {
            return 0;
        }
        if (value > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        }
        return (int) value;
    }
}
