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

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.adam.dto.AdamMemberCodeExcelDto;
import com.liquidnet.client.admin.zhengzai.adam.service.IAdamMemberCodeAdminService;
import com.liquidnet.client.admin.zhengzai.adam.service.IAdamMemberPriceAdminService;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.service.adam.constant.AdamRedisConst;
import com.liquidnet.service.adam.dto.admin.AdamMemberCodeGenParam;
import com.liquidnet.service.adam.dto.admin.AdamMemberCodeListParam;
import com.liquidnet.service.adam.dto.admin.AdamMemberCodeOptParam;
import com.liquidnet.service.adam.dto.vo.AdamMemberCodeVo;
import com.liquidnet.service.adam.entity.AdamMemberCode;
import com.liquidnet.service.adam.entity.AdamMemberPrice;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

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

@Api(tags = "会员码管理")
@Controller
@RequestMapping("adam/mcode")
public class AdamMemberCodeAdminController extends BaseController {
    private final String prefix = "zhengzai/adam/member/code";
    @Autowired
    IAdamMemberCodeAdminService adamMemberCodeAdminService;
    @Autowired
    IAdamMemberPriceAdminService adamMemberPriceAdminService;

    @Autowired
    RedisUtil redisUtil;

    @GetMapping("code/mgt")
    public String viewCodeMgt(@RequestParam String memberId, ModelMap mmap) {
        mmap.put("memberId", memberId);
        return prefix + "/code_mgt";
    }

    @ApiOperation(value = "会员码:管理")
    @RequiresPermissions("adam:member:code:mgt:list")
    @Log(title = "会员管理:会员码:管理", businessType = BusinessType.LIST)
    @PostMapping("code/mgt/list")
    @ResponseBody
    public TableDataInfo listCodeMgt(@RequestParam String memberId) {
        // TODO: 2021/9/23 码生成记录

        return getDataTable(null);
    }

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

    @ApiOperation(value = "会员码:列表")
    @RequiresPermissions("adam:member:code:list")
    @Log(title = "会员管理:会员码:列表", businessType = BusinessType.LIST)
    @PostMapping("code/list")
    @ResponseBody
    public TableDataInfo listCode(AdamMemberCodeListParam parameter) {
        return getDataTable(codeListQuery(parameter));
    }

    private List<AdamMemberCode> codeListQuery(AdamMemberCodeListParam parameter) {
        LambdaQueryWrapper<AdamMemberCode> queryWrapper = Wrappers.lambdaQuery(AdamMemberCode.class).orderByDesc(AdamMemberCode::getCreatedAt);
        queryWrapper.eq(AdamMemberCode::getMemberId, parameter.getMemberId());
        queryWrapper.eq(AdamMemberCode::getType, 2);
        queryWrapper.ne(AdamMemberCode::getState, 2);
        if (null != parameter.getState()) {
            queryWrapper.eq(AdamMemberCode::getState, parameter.getState());
        }
        queryWrapper.select(
                AdamMemberCode::getCode,
                AdamMemberCode::getState,
                AdamMemberCode::getOperator,
                AdamMemberCode::getCreatedAt,
                AdamMemberCode::getValidity,
                AdamMemberCode::getEffectAt,
                AdamMemberCode::getExpireAt,
                AdamMemberCode::getUseOrderNo,
                AdamMemberCode::getUseUid,
                AdamMemberCode::getUseAt
        );
        queryWrapper.orderByDesc(AdamMemberCode::getMemberNo);

        return adamMemberCodeAdminService.list(queryWrapper);
    }

    @ApiOperation(value = "会员码:导出")
    @RequiresPermissions("adam:member:code:export")
    @Log(title = "会员管理:会员码:导出", businessType = BusinessType.EXPORT)
    @PostMapping("code/export")
    @ResponseBody
    public AjaxResult exportCode(AdamMemberCodeListParam parameter) {
        List<AdamMemberCode> list = codeListQuery(parameter);

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

    @ApiOperation(value = "会员码:生成")
    @RequiresPermissions("adam:member:code:gen")
    @Log(title = "会员管理:会员码:生成", businessType = BusinessType.INSERT)
    @PostMapping("code/gen")
    @ResponseBody
    public AjaxResult genCode(@Validated AdamMemberCodeGenParam parameter) {
        int count = adamMemberPriceAdminService.count(
                Wrappers.lambdaQuery(AdamMemberPrice.class)
                        .eq(AdamMemberPrice::getMemberPriceId, parameter.getMemberPriceId())
                        .eq(AdamMemberPrice::getMemberId, parameter.getMemberId())
                        .eq(AdamMemberPrice::getState, 1)
        );
        if (count <= 0) {
            logger.warn("会员卡ID/价格ID无效[{}]", parameter);
            return this.error("会员卡ID/价格ID无效");
        }
        return this.toAjax(adamMemberCodeAdminService.createGiftCode(parameter));
    }

    @RequiresPermissions("adam:member:code:invalid")
    @Log(title = "会员管理:会员码:失效", businessType = BusinessType.UPDATE)
    @PostMapping("invalid_code")
    @ResponseBody
    public AjaxResult invalid(AdamMemberCodeOptParam optParam) {
        return toAjax(this.invalidRecoverCode(optParam, 4));
    }

    /**
     * 失效｜退回会员兑换码
     *
     * @param optParam AdamMemberCodeOptParam
     * @param state    状态[0-可用|1-已用|2-无效|3-过期｜4-失效｜5-退回]
     * @return boolean
     */
    private boolean invalidRecoverCode(AdamMemberCodeOptParam optParam, int state) {
        String loginName = ShiroUtils.getLoginName();
        LocalDateTime now = LocalDateTime.now();
        logger.info("by:{},optParam:{},state:{}", loginName, optParam, state);

        int beforeState = state == 4 ? 0 : (state == 5 ? 1 : -1);
        ArrayList<String> updateCodeList = CollectionUtil.arrayListString();
        optParam.getCodes().forEach(r -> {
            String key = AdamRedisConst.INFO_MEMBER_CODE.concat(r);
            AdamMemberCodeVo vo = (AdamMemberCodeVo) redisUtil.get(key);
            if (null != vo && vo.getState() == beforeState) {
                redisUtil.del(key);

                updateCodeList.add(vo.getCode());
            }
        });

        if (!CollectionUtils.isEmpty(updateCodeList)) {
            LambdaUpdateWrapper<AdamMemberCode> memberCodeUpdateWrapper = Wrappers.lambdaUpdate(AdamMemberCode.class);
            memberCodeUpdateWrapper.eq(AdamMemberCode::getMemberId, optParam.getMemberId());
            memberCodeUpdateWrapper.eq(AdamMemberCode::getState, beforeState);
            memberCodeUpdateWrapper.in(AdamMemberCode::getCode, updateCodeList);

            memberCodeUpdateWrapper.set(AdamMemberCode::getState, state);
            memberCodeUpdateWrapper.set(AdamMemberCode::getOperator, loginName);
            memberCodeUpdateWrapper.set(AdamMemberCode::getUpdatedAt, now);

            return adamMemberCodeAdminService.update(memberCodeUpdateWrapper);
        }
        return false;
    }

    @RequiresPermissions("adam:member:code:recover")
    @Log(title = "会员管理:会员码:退回", businessType = BusinessType.UPDATE)
    @PostMapping("recover_code")
    @ResponseBody
    public AjaxResult recover(AdamMemberCodeOptParam optParam) {
        return toAjax(this.invalidRecoverCode(optParam, 5));
    }
}
