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

import com.baomidou.mybatisplus.core.conditions.Wrapper;
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.poi.ExcelUtil;
import com.liquidnet.client.admin.zhengzai.candy.dto.CandyCouponCodeExcelDto;
import com.liquidnet.client.admin.zhengzai.candy.service.ICandyCouponCodeAdminService;
import com.liquidnet.common.cache.redis.util.RedisUtil;
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 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 RedisUtil redisUtil;
    @Autowired
    private ICandyCouponCodeAdminService candyCouponCodeAdminService;

    @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::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);
        List<CandyCouponCode> list = candyCouponCodeAdminService.list(couponCodeLambdaQueryWrapper);

        List<String> ccodeUpdateList = CollectionUtil.arrayListString();
        list.forEach(r -> {
            String key = CandyRedisConst.BASIC_COUPON_CODE.concat(r.getCcode());
            CandyCouponCodeDto dto = (CandyCouponCodeDto) redisUtil.get(key);
            if (null != dto && dto.getState() == 0) {
                dto.setState(4);
                redisUtil.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> 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);
        List<CandyCouponCode> list = candyCouponCodeAdminService.list(couponCodeLambdaQueryWrapper);

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

            if (!CollectionUtils.isEmpty(vos)) {
                CandyUserCouponBasicDto userCouponBasicDto = vos.parallelStream().filter(v -> v.getCouponId().equals(couponId)).findAny().orElse(null);

                if (null != userCouponBasicDto && userCouponBasicDto.getState() == 1) {
                    String cckey = CandyRedisConst.BASIC_COUPON_CODE.concat(r.getCcode());
                    CandyCouponCodeDto dto = (CandyCouponCodeDto) redisUtil.get(cckey);

                    if (null != dto && dto.getState() == 1) {
                        dto.setState(5);
                        redisUtil.set(cckey, dto);

                        vos.removeIf(vr -> vr.getCouponId().equals(couponId));
                        redisUtil.set(uckey, vos);

                        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(5);
            updateCouponCode.setUpdatedAt(LocalDateTime.now());

            return toAjax(candyCouponCodeAdminService.update(updateCouponCode, couponCodeUpdateWrapper));
        }
        return toAjax(false);
    }
}
