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.zhengzai.candy.service.ICandyCouponAdminService;
import com.liquidnet.client.admin.zhengzai.candy.service.ICandyCouponRuleAdminService;
import com.liquidnet.client.admin.zhengzai.candy.service.ICandyMgtCouponAdminService;
import com.liquidnet.client.admin.zhengzai.kylin.service.impl.KylinPerformancesAdminServiceImpl;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.candy.dto.admin.CandyCouponRuleBuildParam;
import com.liquidnet.service.candy.dto.admin.CandyMgtCouponBuildParam;
import com.liquidnet.service.candy.dto.admin.CandyMgtCouponInfoDto;
import com.liquidnet.service.candy.dto.admin.CandyMgtCouponListParam;
import com.liquidnet.service.candy.entity.CandyCoupon;
import com.liquidnet.service.candy.entity.CandyCouponRule;
import com.liquidnet.service.candy.entity.CandyMgtCoupon;
import com.liquidnet.service.kylin.dao.PerformanceSimpleAllDao;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

@Api(tags = "我的券")
@Controller
@RequestMapping("candy/coupon/mgt")
public class CandyMgtCouponAdminController extends BaseController {
    private final String prefix = "zhengzai/candy/coupon/mgt";

    @Value("${liquidnet.client.admin.phpMallUrl}")
    private String phpMallUrl;

    @Autowired
    private ICandyMgtCouponAdminService candyMgtCouponAdminService;
    @Autowired
    private ICandyCouponAdminService candyCouponAdminService;
    @Autowired
    private ICandyCouponRuleAdminService candyCouponRuleAdminService;
    @Autowired
    private KylinPerformancesAdminServiceImpl kylinPerformancesService;

    @RequiresPermissions("candy:coupon:mgt:view")
    @GetMapping()
    public String coupon(@RequestParam int couType, ModelMap mmap) {
        mmap.put("couType", couType);
        return prefix + "/coupon" + couType;
    }

    @Log(title = "我的券:券列表", businessType = BusinessType.LIST)
    @RequiresPermissions("candy:coupon:mgt:list")
    @PostMapping("list")
    @ResponseBody
    public TableDataInfo list(CandyMgtCouponListParam listParam) {
        startPage();
        List<CandyMgtCouponInfoDto> list = candyMgtCouponAdminService.listForMgtCouponInfoDto(listParam);
        if (!CollectionUtils.isEmpty(list)) {
            if (Arrays.asList(3, 101).contains(listParam.getCouType())) {
                String[] couponIdArr = list.stream().map(CandyMgtCouponInfoDto::getCouponId).toArray(String[]::new);

                LambdaQueryWrapper<CandyCouponRule> queryWrapper = Wrappers.lambdaQuery(CandyCouponRule.class);
                queryWrapper.in(CandyCouponRule::getCouponId, couponIdArr);
                queryWrapper.eq(CandyCouponRule::getState, 1);
                queryWrapper.select(CandyCouponRule::getCruleId, CandyCouponRule::getCouponId, CandyCouponRule::getBusiName);
                List<CandyCouponRule> couponRuleList = candyCouponRuleAdminService.list(queryWrapper);
                list.stream().forEach(r->{
                    couponRuleList.forEach(cr -> {
                        if (r.getCouponId().equals(cr.getCouponId())) {
                            r.setCouponRuleScopeName(cr.getBusiName());
                        }
                    });
                });
            }
        }
        return getDataTable(list);
    }

    @Log(title = "我的券:券详情", businessType = BusinessType.DETAIL)
    @RequiresPermissions("candy:coupon:mgt:detail")
    @GetMapping("detail/{couType}/{mcouponId}")
    public String detail(@PathVariable("couType") int couType,
                         @PathVariable("mcouponId") String mcouponId, ModelMap mmap) {
        CandyMgtCouponListParam listParam = new CandyMgtCouponListParam();
        listParam.setMcouponId(mcouponId);
        List<CandyMgtCouponInfoDto> list = candyMgtCouponAdminService.listForMgtCouponInfoDto(listParam);
        if (!CollectionUtils.isEmpty(list)) {
            CandyMgtCouponInfoDto mgtCouponInfoDto = list.get(0);
            mmap.put("mgtCouponInfoDto", mgtCouponInfoDto);

            LambdaQueryWrapper<CandyCouponRule> queryWrapper = Wrappers.lambdaQuery(CandyCouponRule.class);
            queryWrapper.eq(CandyCouponRule::getCouponId, mgtCouponInfoDto.getCouponId());
            queryWrapper.eq(CandyCouponRule::getState, 1);
            queryWrapper.select(CandyCouponRule::getUseScope, CandyCouponRule::getBusiName, CandyCouponRule::getBusiId);

            List<CandyCouponRule> couponRuleList = candyCouponRuleAdminService.list(queryWrapper);
            if (!CollectionUtils.isEmpty(couponRuleList)) {
                CandyCouponRule couponRule = couponRuleList.get(0);
                mmap.put("couponRule", couponRule);

                switch (mgtCouponInfoDto.getBusiType()) {
                    case 1:// 演出
                        StringBuffer busiNameChildNodeStringBuffer = new StringBuffer();
                        if (Arrays.asList(91, 92).contains(couponRule.getUseScope())) {
                            List<PerformanceSimpleAllDao> performanceSimpleAllDaoList = kylinPerformancesService.getListDetailByStatus("(3,6)", couponRule.getBusiName());
                            PerformanceSimpleAllDao performanceSimpleAllDao = null;
                            switch (couponRule.getUseScope()) {
                                case 91:
                                    performanceSimpleAllDao = performanceSimpleAllDaoList.stream().filter(
                                            r -> r.getTimeId().equals(couponRule.getBusiId())
                                    ).findAny().orElse(null);
                                    if (null != performanceSimpleAllDao) {
                                        busiNameChildNodeStringBuffer.append(" / ").append(performanceSimpleAllDao.getTimeTitle());
                                    }
                                    break;
                                case 92:
                                    performanceSimpleAllDao = performanceSimpleAllDaoList.stream().filter(
                                            r -> r.getTicketId().equals(couponRule.getBusiId())
                                    ).findAny().orElse(null);
                                    if (null != performanceSimpleAllDao) {
                                        busiNameChildNodeStringBuffer.append(" / ").append(performanceSimpleAllDao.getTimeTitle());
                                        busiNameChildNodeStringBuffer.append(" / ").append(performanceSimpleAllDao.getTicketTitle());
                                    }
                                    break;
                            }
                            mmap.put("busiNameChildNode", busiNameChildNodeStringBuffer.toString());
                        }
                        break;
                }
            }
        }
        return prefix + "/detail" + couType;
    }

    @GetMapping("add/{couType}")
    public String add(@PathVariable("couType") String couType, ModelMap mmap) {
        mmap.put("phpMallUrl", phpMallUrl);
        return prefix + "/add" + couType;
    }

    @ApiOperation(value = "新建")
    @Log(title = "我的券:券新建", businessType = BusinessType.INSERT)
    @RequiresPermissions("candy:coupon:mgt:add")
    @PostMapping("add")
    @ResponseBody
    public AjaxResult addSave(@RequestBody @Validated CandyMgtCouponBuildParam buildParam) {
        logger.info("operator:{},buildParam:{}", ShiroUtils.getLoginName(), JsonUtils.toJson(buildParam));
        AjaxResult ajaxResult = this.buildValidProcessing(buildParam);
        if (((int) ajaxResult.get(AjaxResult.CODE_TAG)) != 0) {
            return ajaxResult;
        }
        return toAjax(candyMgtCouponAdminService.saveMgtCouponForCouponBuild(buildParam));
    }

    private AjaxResult buildValidProcessing(CandyMgtCouponBuildParam buildParam) {
        switch (buildParam.getCouType()) {
            case 1:// 代金券
                BigDecimal valFace = buildParam.getValFace();
                if (null == valFace || valFace.compareTo(BigDecimal.ZERO) <= 0) {
                    return AjaxResult.warn("代金券金额无效");
                }
                buildParam.setDiscount(null);
                buildParam.setValOver(null);
                buildParam.setValMinus(null);
                buildParam.setOverlay(0);
                break;
            case 2:// 满减券
                BigDecimal valOver = buildParam.getValOver();
                BigDecimal valMinus = buildParam.getValMinus();
                if (null == valOver || valOver.compareTo(BigDecimal.ZERO) <= 0
                        || null == valMinus || valMinus.compareTo(BigDecimal.ZERO) <= 0) {
                    return AjaxResult.warn("满减金额无效");
                }
                buildParam.setDiscount(null);
                buildParam.setValFace(valMinus);
                buildParam.setOverlay(0);
                break;
            case 3:// 兑换券
                buildParam.setBindType(0);
                buildParam.setDiscount(null);
                buildParam.setValFace(null);
                buildParam.setValOver(null);
                buildParam.setValMinus(null);
                buildParam.setOverlay(0);
                break;
            case 4:// 折扣券
                BigDecimal discount = buildParam.getDiscount();
                if (null == discount || discount.compareTo(BigDecimal.ZERO) <= 0) {
                    return AjaxResult.warn("折扣配置无效");
                }
                if (buildParam.getBusiType() != 2) {
                    return AjaxResult.warn("当前类别不支持折扣券");
                }
                buildParam.setValFace(null);
                buildParam.setValOver(null);
                buildParam.setValMinus(null);
                break;
            case 101:// 优先券
                if (null == buildParam.getOverlay()) {
                    return AjaxResult.warn("叠加限制配置无效");
                }
                if (buildParam.getBusiType() != 3) {
                    return AjaxResult.warn("当前类别不支持优先券");
                }
                buildParam.setDiscount(null);
                buildParam.setValFace(null);
                buildParam.setValOver(null);
                buildParam.setValMinus(null);
                break;
            default:
                logger.warn("Invalid operation[buildParam.couType={}]", buildParam.getCouType());
                return this.error(AjaxResult.Type.WARN, "券类型无效");
        }

        if (buildParam.getBusiType() > 0) {// 校验适用范围
            List<CandyCouponRuleBuildParam> couponRuleList = buildParam.getCouponRuleList();
            if (CollectionUtils.isEmpty(couponRuleList)) {
                return AjaxResult.warn("请指定适用范围");
            }
            CandyCouponRuleBuildParam couponRuleBuildParam = couponRuleList.get(0);
            if (couponRuleBuildParam.getUseScope() != 100 && (
                    StringUtils.isEmpty(couponRuleBuildParam.getBusiId()) || StringUtils.isEmpty(couponRuleBuildParam.getBusiName())
            )) {
                return AjaxResult.warn("请指定具体适用内容");
            }
        } else {
            buildParam.setCouponRuleList(null);
        }

//        if (0 == buildParam.getBindType()) {
//            buildParam.setEventType(0);
//            buildParam.setEventLimit(null);
//            if (null == buildParam.getRedeemValidity()) {
//                return AjaxResult.warn("兑换有效期无效");
//            }
//        } else {
//            if (buildParam.getEventType() == 2) {// 指定用户手机号
//                if (StringUtils.isBlank(buildParam.getEventLimit())) {
//                    return AjaxResult.warn("请指定手机号");
//                }
//            }
//        }

        switch (buildParam.getBindType()) {// 领取方式[0-用户输入兑换｜1-发放至用户｜2-积分兑换]
            case 0:
                buildParam.setEventType(0);
                buildParam.setEventLimit(null);
                if (null == buildParam.getRedeemValidity()) {
                    return AjaxResult.warn("兑换有效期无效");
                }
                break;
            case 1:
                if (buildParam.getEventType() == 2) {// 指定用户手机号
                    if (StringUtils.isBlank(buildParam.getEventLimit())) {
                        return AjaxResult.warn("请指定手机号");
                    }
                }
                break;
            case 2:// TODO: 2021/11/9 PM上线前临时加的券领取类型（2-积分兑换）
                buildParam.setEventType(0);
                buildParam.setEventLimit(null);
                break;
            default:
                logger.warn("Invalid operation[buildParam.bindType={}]", buildParam.getBindType());
                return this.error(AjaxResult.Type.WARN, "券领取方式无效");
        }
        return AjaxResult.success();
    }

    @ApiOperation(value = "编辑")
    @Log(title = "我的券:券编辑", businessType = BusinessType.UPDATE)
    @RequiresPermissions("candy:coupon:mgt:edit")
    @PostMapping("edit")
    @ResponseBody
    public AjaxResult editSave(@RequestBody @Validated CandyMgtCouponBuildParam buildParam) {
        logger.info("operator:{},buildParam:{}", ShiroUtils.getLoginName(), buildParam);
        if (StringUtils.isBlank(buildParam.getMcouponId())) {
            return AjaxResult.warn("发放ID【mcouponId】不能为空");
        }
        AjaxResult ajaxResult = this.buildValidProcessing(buildParam);
        if (((int) ajaxResult.get(AjaxResult.CODE_TAG)) != 0) {
            return ajaxResult;
        }
        return toAjax(candyMgtCouponAdminService.editMgtCouponForCouponBuild(buildParam));
    }

    @Log(title = "我的券:券取消", businessType = BusinessType.CANCEL)
    @RequiresPermissions("candy:coupon:mgt:cancel")
    @GetMapping("cancel/{mcouponId}")
    @ResponseBody
    public AjaxResult cancel(@PathVariable("mcouponId") String mcouponId) {
        LambdaQueryWrapper<CandyMgtCoupon> mgtCouponLambdaQueryWrapper = Wrappers.lambdaQuery(CandyMgtCoupon.class);
        mgtCouponLambdaQueryWrapper.eq(CandyMgtCoupon::getMcouponId, mcouponId);
        CandyMgtCoupon mgtCoupon = candyMgtCouponAdminService.getOne(mgtCouponLambdaQueryWrapper);
        if (null == mgtCoupon) {
            return AjaxResult.warn(String.format("券记录不存在【%s】", mcouponId));
        }
        if (mgtCoupon.getState() == 1) {
            return AjaxResult.warn("券记录已完成发放");
        }
        if (mgtCoupon.getState() == 9) {
            return AjaxResult.warn("券记录已开始发放");
        }
        if (mgtCoupon.getState() != 0) {
            return AjaxResult.warn("券记录不可取消");
        }
        LocalDateTime now = LocalDateTime.now();
        String loginName = ShiroUtils.getLoginName();

        LambdaUpdateWrapper<CandyMgtCoupon> mgtCouponLambdaUpdateWrapper = Wrappers.lambdaUpdate(CandyMgtCoupon.class);
        mgtCouponLambdaUpdateWrapper.eq(CandyMgtCoupon::getMcouponId, mcouponId);
        mgtCouponLambdaUpdateWrapper.eq(CandyMgtCoupon::getState, 0);
        mgtCouponLambdaUpdateWrapper.set(CandyMgtCoupon::getState, 3);
        mgtCouponLambdaUpdateWrapper.set(CandyMgtCoupon::getUpdatedAt, now);
        mgtCouponLambdaUpdateWrapper.set(CandyMgtCoupon::getOperator, loginName);
        boolean updateMgtCouponFlg = candyMgtCouponAdminService.update(mgtCouponLambdaUpdateWrapper);
        if (!updateMgtCouponFlg) {
            return AjaxResult.warn("券记录取消失败，已发放或正在发放中");
        }

        LambdaUpdateWrapper<CandyCoupon> couponLambdaUpdateWrapper = Wrappers.lambdaUpdate(CandyCoupon.class);
        couponLambdaUpdateWrapper.eq(CandyCoupon::getCouponId, mgtCoupon.getCouponId());
        couponLambdaUpdateWrapper.set(CandyCoupon::getState, 2);
        couponLambdaUpdateWrapper.set(CandyCoupon::getUpdatedAt, now);
        couponLambdaUpdateWrapper.set(CandyCoupon::getOperator, loginName);
        candyCouponAdminService.update(couponLambdaUpdateWrapper);

        LambdaUpdateWrapper<CandyCouponRule> couponRuleLambdaUpdateWrapper = Wrappers.lambdaUpdate(CandyCouponRule.class);
        couponRuleLambdaUpdateWrapper.eq(CandyCouponRule::getCouponId, mgtCoupon.getCouponId());
        couponRuleLambdaUpdateWrapper.set(CandyCouponRule::getState, 2);
        candyCouponRuleAdminService.update(couponRuleLambdaUpdateWrapper);
        return toAjax(updateMgtCouponFlg);
    }
}
