package com.liquidnet.client.admin.web.controller.zhengzai.candy;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.liquidnet.client.admin.common.annotation.Log;
import com.liquidnet.client.admin.common.core.controller.BaseController;
import com.liquidnet.client.admin.common.core.domain.AjaxResult;
import com.liquidnet.client.admin.common.core.page.TableDataInfo;
import com.liquidnet.client.admin.common.enums.BusinessType;
import com.liquidnet.client.admin.common.utils.ShiroUtils;
import com.liquidnet.client.admin.common.utils.poi.ExcelUtil;
import com.liquidnet.client.admin.zhengzai.candy.dto.CandyCouponCodeExcelDto;
import com.liquidnet.client.admin.zhengzai.candy.service.ICandyCouponCodeAdminService;
import com.liquidnet.client.admin.zhengzai.candy.service.ICandyUserCouponAdminService;
import com.liquidnet.common.cache.redis.util.AbstractRedisUtil;
import com.liquidnet.common.cache.redis.util.RedisDataSourceUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.candy.constant.CandyRedisConst;
import com.liquidnet.service.candy.dto.CandyCouponCodeDto;
import com.liquidnet.service.candy.dto.CandyUserCouponBasicDto;
import com.liquidnet.service.candy.dto.admin.CandyCouponCodeListParam;
import com.liquidnet.service.candy.dto.admin.CandyCouponCodeOptParam;
import com.liquidnet.service.candy.entity.CandyCouponCode;
import com.liquidnet.service.candy.entity.CandyUserCoupon;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

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

@Controller
@RequestMapping("candy/coupon/code")
public class CandyCouponCodeAdminController extends BaseController {
    private String prefix = "zhengzai/candy/coupon/code";

    @Autowired
    private RedisDataSourceUtil redisDataSourceUtil;
    @Autowired
    private ICandyCouponCodeAdminService candyCouponCodeAdminService;
    @Autowired
    private ICandyUserCouponAdminService candyUserCouponAdminService;

    @GetMapping()
    public String view(@RequestParam String couponId, ModelMap mmap) {
        mmap.put("couponId", couponId);
        return prefix + "/code";
    }

    @RequiresPermissions("candy:coupon:code:list")
    @Log(title = "我的券:券码管理:列表", businessType = BusinessType.LIST)
    @PostMapping("list")
    @ResponseBody
    public TableDataInfo list(CandyCouponCodeListParam listParam) {
        startPage();
        return getDataTable(listQuery(listParam));
    }

    private List<CandyCouponCode> listQuery(CandyCouponCodeListParam listParam) {
        LambdaQueryWrapper<CandyCouponCode> lambdaQuery = Wrappers.lambdaQuery(CandyCouponCode.class);
        lambdaQuery.eq(CandyCouponCode::getCouponId, listParam.getCouponId())
                .ne(CandyCouponCode::getState, 2)
                .select(
                        CandyCouponCode::getCcode,
                        CandyCouponCode::getCouponId,
                        CandyCouponCode::getUcouponId,
                        CandyCouponCode::getRedeemMobile,
                        CandyCouponCode::getState
                );
        if (null != listParam.getState()) {
            lambdaQuery.eq(CandyCouponCode::getState, listParam.getState());
        }
        return candyCouponCodeAdminService.list(lambdaQuery);
    }

    @RequiresPermissions("candy:coupon:code:export")
    @Log(title = "我的券:券码管理:导出", businessType = BusinessType.EXPORT)
    @PostMapping("export")
    @ResponseBody
    public AjaxResult export(CandyCouponCodeListParam listParam) {
        List<CandyCouponCode> list = listQuery(listParam);

        ExcelUtil<CandyCouponCodeExcelDto> excelUtil = new ExcelUtil<>(CandyCouponCodeExcelDto.class);
        List<CandyCouponCodeExcelDto> excelList = new ArrayList<>();
        list.forEach(r -> {
            excelList.add(CandyCouponCodeExcelDto.getNew().copy(r));
        });
        return excelUtil.exportExcel(excelList, "券码数据");
    }

    @RequiresPermissions("candy:coupon:code:invalid")
    @Log(title = "我的券:券码管理:失效", businessType = BusinessType.UPDATE)
    @PostMapping("invalid")
    @ResponseBody
    public AjaxResult invalid(CandyCouponCodeOptParam optParam) {
        logger.info("optParam:{}", JsonUtils.toJson(optParam));
        if (null == optParam) {
            return AjaxResult.warn("无效传参");
        }
        String couponId = optParam.getCouponId();
        List<String> ccodes = optParam.getCcodes();
        if (StringUtils.isBlank(couponId) || CollectionUtils.isEmpty(ccodes)) {
            return AjaxResult.warn("参数无效");
        }

        LambdaQueryWrapper<CandyCouponCode> couponCodeLambdaQueryWrapper = Wrappers.lambdaQuery(CandyCouponCode.class);
        couponCodeLambdaQueryWrapper.in(CandyCouponCode::getCcode, ccodes);
        couponCodeLambdaQueryWrapper.eq(CandyCouponCode::getCouponId, couponId);
        couponCodeLambdaQueryWrapper.eq(CandyCouponCode::getState, 0);
        List<CandyCouponCode> list = candyCouponCodeAdminService.list(couponCodeLambdaQueryWrapper);

        AbstractRedisUtil redisCandyUtil = redisDataSourceUtil.getRedisCandyUtil();
        List<String> ccodeUpdateList = CollectionUtil.arrayListString();
        list.forEach(r -> {
            String key = CandyRedisConst.BASIC_COUPON_CODE.concat(r.getCcode());
            CandyCouponCodeDto dto = (CandyCouponCodeDto) redisCandyUtil.get(key);
            if (null != dto && dto.getState() == 0) {
                dto.setState(4);
                redisCandyUtil.set(key, dto);
                ccodeUpdateList.add(dto.getCcode());
            }
        });

        if (!CollectionUtils.isEmpty(ccodeUpdateList)) {
            LambdaUpdateWrapper<CandyCouponCode> couponCodeUpdateWrapper = Wrappers.lambdaUpdate(CandyCouponCode.class);
            couponCodeUpdateWrapper.in(CandyCouponCode::getCcode, ccodeUpdateList).eq(CandyCouponCode::getCouponId, couponId);

            CandyCouponCode updateCouponCode = new CandyCouponCode();
            updateCouponCode.setState(4);
            updateCouponCode.setUpdatedAt(LocalDateTime.now());
            return toAjax(candyCouponCodeAdminService.update(updateCouponCode, couponCodeUpdateWrapper));
        }
        return toAjax(false);
    }

    @RequiresPermissions("candy:coupon:code:recover")
    @Log(title = "我的券:券码管理:退回", businessType = BusinessType.UPDATE)
    @PostMapping("recover")
    @ResponseBody
    public AjaxResult recover(CandyCouponCodeOptParam optParam) {
        logger.info("optParam:{}", JsonUtils.toJson(optParam));
        if (null == optParam) {
            return AjaxResult.warn("无效传参");
        }
        String couponId = optParam.getCouponId();
        List<String> ucouponIds = optParam.getUcouponIds();
        if (StringUtils.isBlank(couponId) || CollectionUtils.isEmpty(ucouponIds)) {
            return AjaxResult.warn("参数无效");
        }

        LambdaQueryWrapper<CandyCouponCode> couponCodeLambdaQueryWrapper = Wrappers.lambdaQuery(CandyCouponCode.class);
        couponCodeLambdaQueryWrapper.in(CandyCouponCode::getUcouponId, ucouponIds);
        couponCodeLambdaQueryWrapper.eq(CandyCouponCode::getCouponId, couponId);
        couponCodeLambdaQueryWrapper.eq(CandyCouponCode::getState, 1);
        couponCodeLambdaQueryWrapper.select(CandyCouponCode::getCouponId, CandyCouponCode::getUcouponId, CandyCouponCode::getRedeemUid);
        List<CandyCouponCode> list = candyCouponCodeAdminService.list(couponCodeLambdaQueryWrapper);

        AbstractRedisUtil redisCandyUtil = redisDataSourceUtil.getRedisCandyUtil();
        List<String> ccodeUpdateList = CollectionUtil.arrayListString();
        list.forEach(r -> {
            String uckey = CandyRedisConst.BASIC_USER_COUPON.concat(r.getRedeemUid());
            List<CandyUserCouponBasicDto> vos = (List<CandyUserCouponBasicDto>) redisCandyUtil.get(uckey);

            if (!CollectionUtils.isEmpty(vos)) {
                vos.removeIf(rv -> rv.getUcouponId().equals(r.getUcouponId()));
            }

            redisCandyUtil.set(uckey, vos);

            ccodeUpdateList.add(r.getUcouponId());
        });

        if (!CollectionUtils.isEmpty(ccodeUpdateList)) {
            LocalDateTime now = LocalDateTime.now();
            String loginName = ShiroUtils.getLoginName(), comment = "RECOVER";

            LambdaUpdateWrapper<CandyUserCoupon> userCouponLambdaUpdateWrapper = Wrappers.lambdaUpdate(CandyUserCoupon.class);
            userCouponLambdaUpdateWrapper.in(CandyUserCoupon::getUcouponId, ccodeUpdateList);
            userCouponLambdaUpdateWrapper.eq(CandyUserCoupon::getCouponId, couponId);

            userCouponLambdaUpdateWrapper.set(CandyUserCoupon::getState, 2);
            userCouponLambdaUpdateWrapper.set(CandyUserCoupon::getUpdatedAt, now);
            userCouponLambdaUpdateWrapper.set(CandyUserCoupon::getOperator, loginName);
            userCouponLambdaUpdateWrapper.set(CandyUserCoupon::getComment, comment);
            boolean update = candyUserCouponAdminService.update(userCouponLambdaUpdateWrapper);
            logger.info("Recover:coupon.code:[couponId={},updateUserCouponRst={}]", couponId, update);

            LambdaUpdateWrapper<CandyCouponCode> couponCodeUpdateWrapper = Wrappers.lambdaUpdate(CandyCouponCode.class);
            couponCodeUpdateWrapper.in(CandyCouponCode::getUcouponId, ccodeUpdateList);
            couponCodeUpdateWrapper.eq(CandyCouponCode::getCouponId, couponId);

            couponCodeUpdateWrapper.set(CandyCouponCode::getState, 5);
            couponCodeUpdateWrapper.set(CandyCouponCode::getUpdatedAt, now);
            couponCodeUpdateWrapper.set(CandyCouponCode::getOperator, loginName);
            couponCodeUpdateWrapper.set(CandyCouponCode::getComment, comment);
            update = candyCouponCodeAdminService.update(couponCodeUpdateWrapper);
            logger.info("Recover:coupon.code:[couponId={},updateCouponCodeRst={}]", couponId, update);

            return toAjax(update);
        }
        return toAjax(false);
    }
}
