package com.gxwebsoft.shop.controller;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.entity.ShopCoupon;
import com.gxwebsoft.shop.entity.ShopCouponApplyCate;
import com.gxwebsoft.shop.entity.ShopCouponApplyItem;
import com.gxwebsoft.shop.service.ShopCouponApplyCateService;
import com.gxwebsoft.shop.service.ShopCouponApplyItemService;
import com.gxwebsoft.shop.service.ShopCouponService;
import com.gxwebsoft.shop.service.ShopUserCouponService;
import com.gxwebsoft.shop.service.CouponStatusService;
import com.gxwebsoft.shop.entity.ShopUserCoupon;
import com.gxwebsoft.shop.param.ShopUserCouponParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;

import javax.annotation.Resource;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * 用户优惠券控制器
 *
 * @author 科技小王子
 * @since 2025-08-11 23:51:41
 */
@Slf4j
@Tag(name = "用户优惠券管理")
@RestController
@RequestMapping("/api/shop/shop-user-coupon")
public class ShopUserCouponController extends BaseController {
    @Resource
    private ShopUserCouponService shopUserCouponService;
    @Resource
    private ShopCouponService couponService;
    @Resource
    private ShopCouponApplyCateService couponApplyCateService;
    @Resource
    private ShopCouponApplyItemService couponApplyItemService;
    @Resource
    private CouponStatusService couponStatusService;

    @Operation(summary = "用户优惠券列表")
    @PostMapping("/list")
    public ApiResult<List<ShopUserCoupon>> list(@RequestBody ShopUserCoupon userCouponParam) throws ParseException {
        MPJLambdaWrapper<ShopUserCoupon> queryWrapper = new MPJLambdaWrapper<ShopUserCoupon>()
                .selectAll(ShopUserCoupon.class)
                .selectAs(ShopCoupon::getName, ShopCoupon::getName)
                .eq(ShopUserCoupon::getUserId, getLoginUserId())
                .leftJoin(ShopCoupon.class, ShopCoupon::getId, ShopUserCoupon::getCouponId);
        if (userCouponParam.getIsExpire() != null)
            queryWrapper.eq(ShopUserCoupon::getIsExpire, userCouponParam.getIsExpire());
        if (userCouponParam.getIsUse() != null) queryWrapper.eq(ShopUserCoupon::getIsUse, userCouponParam.getIsUse());
        List<ShopUserCoupon> userCouponList = shopUserCouponService.list(queryWrapper);
        for (ShopUserCoupon userCoupon : userCouponList) {
            try {
                // 使用新的状态管理服务检查和更新状态
                couponStatusService.checkAndUpdateCouponStatus(userCoupon);

                // 确保BigDecimal字段不为null时才处理
                if (userCoupon.getReducePrice() == null) {
                    userCoupon.setReducePrice(BigDecimal.ZERO);
                }
                if (userCoupon.getMinPrice() == null) {
                    userCoupon.setMinPrice(BigDecimal.ZERO);
                }

                ShopCoupon coupon = couponService.getById(userCoupon.getCouponId());
                if (coupon != null) {
                    // 确保优惠券模板的BigDecimal字段不为null
                    if (coupon.getReducePrice() == null) {
                        coupon.setReducePrice(BigDecimal.ZERO);
                    }
                    if (coupon.getMinPrice() == null) {
                        coupon.setMinPrice(BigDecimal.ZERO);
                    }

                    coupon.setCouponApplyCateList(couponApplyCateService.list(
                            new LambdaQueryWrapper<ShopCouponApplyCate>()
                                    .eq(ShopCouponApplyCate::getCouponId, userCoupon.getCouponId())
                    ));
                    coupon.setCouponApplyItemList(couponApplyItemService.list(
                            new LambdaQueryWrapper<ShopCouponApplyItem>()
                                    .eq(ShopCouponApplyItem::getCouponId, userCoupon.getCouponId())
                    ));
                    userCoupon.setCouponItem(coupon);
                }
            } catch (Exception e) {
                log.error("处理用户优惠券数据异常: {}", e.getMessage(), e);
                // 设置默认值避免序列化异常
                if (userCoupon.getReducePrice() == null) {
                    userCoupon.setReducePrice(BigDecimal.ZERO);
                }
                if (userCoupon.getMinPrice() == null) {
                    userCoupon.setMinPrice(BigDecimal.ZERO);
                }
            }
        }
        return success(userCouponList);
    }

    @Operation(summary = "领取优惠券")
    @PostMapping("/take")
    public ApiResult<?> take(@RequestBody ShopUserCoupon userCoupon) {
      final User loginUser = getLoginUser();
      if (loginUser == null) return fail("请先登录");
      ShopCoupon coupon = couponService.getByIdRel(userCoupon.getCouponId());

      // 检查优惠券是否存在
      if (coupon == null) return fail("优惠券不存在");

      // 安全地检查已领取数量，避免空指针异常
      Integer receiveNum = coupon.getReceiveNum();
      if (receiveNum == null) receiveNum = 0;

      if (coupon.getTotalCount() != -1 && receiveNum >= coupon.getTotalCount()) return fail("已经被领完了");
        List<ShopUserCoupon> userCouponList = shopUserCouponService.list(
                new LambdaQueryWrapper<ShopUserCoupon>()
                        .eq(ShopUserCoupon::getCouponId, userCoupon.getCouponId())
                        .eq(ShopUserCoupon::getUserId, getLoginUserId())
        );
        int userNotUsedNum = 0;
        for (ShopUserCoupon userCouponItem : userCouponList) {
            if (userCouponItem.getIsUse().equals(0)) userNotUsedNum++;
        }
        if (userNotUsedNum > 0) return fail("您还有未使用的优惠券,无法领取");
        if (coupon.getLimitPerUser() > -1) {
            if (userCouponList.size() >= coupon.getLimitPerUser())
                return fail("每用户最多领取" + coupon.getLimitPerUser() + "张优惠券");
        }
        userCoupon.setType(coupon.getType());
        userCoupon.setReducePrice(coupon.getReducePrice());
        userCoupon.setDiscount(coupon.getDiscount());
        userCoupon.setMinPrice(coupon.getMinPrice());
        Integer expireType = coupon.getExpireType();
        userCoupon.setExpireType(expireType);
        if (expireType == 10) {
            userCoupon.setStartTime(LocalDateTime.now());
            userCoupon.setEndTime(LocalDateTimeUtil.offset(userCoupon.getStartTime(), coupon.getExpireDay(), ChronoUnit.DAYS));
        } else {
            userCoupon.setStartTime(coupon.getStartTime());
            userCoupon.setEndTime(coupon.getEndTime());
        }
        userCoupon.setUserId(getLoginUserId());
        shopUserCouponService.save(userCoupon);

        // 安全地更新已领取数量，避免空指针异常
        Integer currentReceiveNum = coupon.getReceiveNum();
        if (currentReceiveNum == null) currentReceiveNum = 0;
        coupon.setReceiveNum(currentReceiveNum + 1);
        couponService.updateById(coupon);
        return success("领取成功");
    }

    @Operation(summary = "分页查询用户优惠券")
    @GetMapping("/page")
    public ApiResult<PageResult<ShopUserCoupon>> page(ShopUserCouponParam param) {
        // 使用关联查询
        return success(shopUserCouponService.pageRel(param));
    }

    @PreAuthorize("hasAuthority('shop:shopUserCoupon:list')")
    @Operation(summary = "查询全部用户优惠券")
    @GetMapping()
    public ApiResult<List<ShopUserCoupon>> list(ShopUserCouponParam param) {
        // 使用关联查询
        return success(shopUserCouponService.listRel(param));
    }

    @PreAuthorize("hasAuthority('shop:shopUserCoupon:list')")
    @Operation(summary = "根据id查询用户优惠券")
    @GetMapping("/{id}")
    public ApiResult<ShopUserCoupon> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(shopUserCouponService.getByIdRel(id));
    }

    @PreAuthorize("hasAuthority('shop:shopUserCoupon:save')")
    @OperationLog
    @Operation(summary = "添加用户优惠券")
    @PostMapping()
    public ApiResult<?> save(@RequestBody ShopUserCoupon shopUserCoupon) {
        // 记录当前登录用户id
        User loginUser = getLoginUser();
        if (loginUser != null) {
            shopUserCoupon.setUserId(loginUser.getUserId());
        }
        if (shopUserCouponService.save(shopUserCoupon)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('shop:shopUserCoupon:update')")
    @OperationLog
    @Operation(summary = "修改用户优惠券")
    @PutMapping()
    public ApiResult<?> update(@RequestBody ShopUserCoupon shopUserCoupon) {
        if (shopUserCouponService.updateById(shopUserCoupon)) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('shop:shopUserCoupon:remove')")
    @OperationLog
    @Operation(summary = "删除用户优惠券")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (shopUserCouponService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @PreAuthorize("hasAuthority('shop:shopUserCoupon:save')")
    @OperationLog
    @Operation(summary = "批量添加用户优惠券")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<ShopUserCoupon> list) {
        if (shopUserCouponService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('shop:shopUserCoupon:update')")
    @OperationLog
    @Operation(summary = "批量修改用户优惠券")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopUserCoupon> batchParam) {
        if (batchParam.update(shopUserCouponService, "id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('shop:shopUserCoupon:remove')")
    @OperationLog
    @Operation(summary = "批量删除用户优惠券")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (shopUserCouponService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @Operation(summary = "获取我的可用优惠券")
    @GetMapping("/my/available")
    public ApiResult<List<ShopUserCoupon>> getMyAvailableCoupons() {
        try {
            List<ShopUserCoupon> coupons = couponStatusService.getAvailableCoupons(getLoginUserId());
            return success("获取成功", coupons);
        } catch (Exception e) {
            return fail("获取失败",null);
        }
    }

    @Operation(summary = "获取我的已使用优惠券")
    @GetMapping("/my/used")
    public ApiResult<List<ShopUserCoupon>> getMyUsedCoupons() {
        try {
            List<ShopUserCoupon> coupons = couponStatusService.getUsedCoupons(getLoginUserId());
            return success("获取成功", coupons);
        } catch (Exception e) {
            return fail("获取失败",null);
        }
    }

    @Operation(summary = "获取我的已过期优惠券")
    @GetMapping("/my/expired")
    public ApiResult<List<ShopUserCoupon>> getMyExpiredCoupons() {
        try {
            List<ShopUserCoupon> coupons = couponStatusService.getExpiredCoupons(getLoginUserId());
            return success("获取成功", coupons);
        } catch (Exception e) {
            return fail("获取失败",null);
        }
    }

    @Operation(summary = "获取我的优惠券统计")
    @GetMapping("/my/statistics")
    public ApiResult<CouponStatusService.CouponStatusResult> getMyCouponStatistics() {
        try {
            CouponStatusService.CouponStatusResult result =
                couponStatusService.getUserCouponsGroupByStatus(getLoginUserId());
            return success("获取成功", result);
        } catch (Exception e) {
            return fail("获取失败",null);
        }
    }

}
