package com.liquidnet.service.goblin.controller.manage;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.liquidnet.common.exception.constant.ErrorCode;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtConfigEditParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtNoticeActionParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtNoticeAddParam;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtNoticeFilterParam;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinStoreMgtInfoVo;
import com.liquidnet.service.goblin.dto.manage.vo.GoblinStoreMgtThumbVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreCertInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreConfigVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreNoticeVo;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtNoticeService;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtService;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@ApiSupport(order = 149002)
@Api(tags = "店铺管理")
@Slf4j
@Validated
@RestController
@RequestMapping("store/mgt")
public class GoblinStoreMgtController {
    @Autowired
    GoblinRedisUtils goblinRedisUtils;
    @Autowired
    IGoblinStoreMgtService goblinStoreMgtService;
    @Autowired
    IGoblinStoreMgtNoticeService goblinStoreMgtNoticeService;

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "店铺管理:店铺列表")
    @GetMapping(value = {"list"})
    public ResponseDto<List<GoblinStoreMgtThumbVo>> thumbList() {
        ArrayList<GoblinStoreMgtThumbVo> storeMgtThumbList = ObjectUtil.getGoblinStoreMgtThumbVoArrayList();

        GoblinStoreInfoVo storeInfoVo = goblinRedisUtils.getStoreInfoVoByUid(CurrentUtil.getCurrentUid());
        if (null != storeInfoVo) {
            storeMgtThumbList.add(GoblinStoreMgtThumbVo.getNew().copy(storeInfoVo));
        }

        return ResponseDto.success(storeMgtThumbList);
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "店铺管理:店铺信息")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "storeId", value = "店铺ID[64]"),
    })
    @GetMapping(value = {"info"})
    public ResponseDto<GoblinStoreMgtInfoVo> info(@NotBlank(message = "店铺ID不能为空") @RequestParam String storeId) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            log.warn("店铺管理:店铺信息:无权查看该店铺[UID={},storeId={}]", currentUid, storeId);
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        return ResponseDto.success(GoblinStoreMgtInfoVo.getNew().copy(goblinRedisUtils.getStoreInfoVo(storeId)));
    }

    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "店铺管理:店铺信息:修改")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "storeId", value = "店铺ID[64]"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "storeName", value = "店铺名称[128]"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "logoPic", value = "店铺LOGO[256]"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "backgroundPic", value = "店铺背景图[256]"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "introduce", value = "店铺介绍[500]"),
    })
    @GetMapping(value = {"info/edit"})
    public ResponseDto<Object> infoEdit(@NotBlank(message = "店铺名称不能为空") @Size(max = 128) @RequestParam String storeName,
                                                      @NotBlank(message = "店铺LOGO不能为空") @Size(max = 256) @RequestParam String logoPic,
                                                      @NotBlank(message = "店铺背景图不能为空") @Size(max = 256) @RequestParam String backgroundPic,
                                                      @NotBlank(message = "店铺介绍不能为空") @Size(max = 500) @RequestParam String introduce,
                                                      @NotBlank(message = "店铺ID不能为空") @Size(max = 64) @RequestParam String storeId) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        GoblinStoreInfoVo storeInfoVo = goblinRedisUtils.getStoreInfoVo(storeId);
        storeInfoVo.setStoreName(storeName);
        storeInfoVo.setLogoPic(logoPic);
        storeInfoVo.setBackgroundPic(backgroundPic);
        storeInfoVo.setIntroduce(introduce);
        storeInfoVo.setUpdatedBy(currentUid);
        storeInfoVo.setUpdatedAt(LocalDateTime.now());

        return goblinStoreMgtService.updateStoreMgtInfo(storeInfoVo) ? ResponseDto.success() : ResponseDto.failure(ErrorMapping.get("149003"));
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "店铺管理:认证信息")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "storeId", value = "店铺ID[64]"),
    })
    @GetMapping(value = {"info/cer"})
    public ResponseDto<GoblinStoreCertInfoVo> certInfo(@NotBlank(message = "店铺ID不能为空") @Size(max = 64) @RequestParam String storeId) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            log.warn("店铺管理:认证信息:无权查看该店铺[UID={},storeId={}]", currentUid, storeId);
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        return ResponseDto.success(GoblinStoreCertInfoVo.getNew().copy(goblinRedisUtils.getStoreInfoVo(storeId)));
    }

    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "店铺管理:店铺设置:详情", notes = "BUSINESS_STATUS（状态:营业状态[4-停业|5-营业]）、ONOFF_CUSTOMER_SEV（开关:联系客服）、ONOFF_SOLD_OUT_SHOW（开关:售罄展示）、LIMIT_WARNING_STOCK（指标:库存不足）")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "storeId", value = "店铺ID[64]"),
    })
    @GetMapping(value = {"conf"})
    public ResponseDto<Map<String, String>> conf(@NotBlank(message = "店铺ID不能为空") @Size(max = 64) @RequestParam String storeId) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            log.warn("店铺管理:店铺设置:无权查看该店铺[UID={},storeId={}]", currentUid, storeId);
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        List<GoblinStoreConfigVo> storeConfigVos = goblinRedisUtils.getStoreConfigVos(storeId);
        return ResponseDto.success(storeConfigVos.stream().collect(Collectors.toMap(GoblinStoreConfigVo::getConfigKey, GoblinStoreConfigVo::getConfigVal)));
    }

    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "店铺管理:店铺设置:编辑")
    @PostMapping(value = {"conf/edit"})
    public ResponseDto<Object> confEdit(@Valid @RequestBody GoblinStoreMgtConfigEditParam param) {
        String currentUid = CurrentUtil.getCurrentUid();
        String storeId = param.getStoreId();
        if (!goblinRedisUtils.hasStoreId(currentUid, storeId)) {
            log.warn("店铺管理:店铺设置:无权编辑该店铺[UID={},storeId={}]", currentUid, storeId);
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (log.isDebugEnabled()) {
            log.debug("店铺管理:店铺设置:编辑[UID={},GoblinStoreMgtConfigEditParam={}]", currentUid, JsonUtils.toJson(param));
        }
        HashMap<String, String> updateConfMap = CollectionUtil.mapStringString();
        param.getConfMap().forEach((ck, cv) -> {
            switch (ck) {
                case "BUSINESS_STATUS":
                    if (Arrays.asList("4", "5").contains(cv)) {
                        // TODO: 2022/2/23 ==zhanggb 暂不启用停业功能
//                        updateConfMap.put(ck, cv);
                        updateConfMap.put(ck, "5");
                    }
                    break;
                case "ONOFF_CUSTOMER_SEV":
                case "ONOFF_SOLD_OUT_SHOW":
                    if (Arrays.asList("ON", "OFF").contains(cv)) {
                        updateConfMap.put(ck, cv);
                    }
                case "LIMIT_WARNING_STOCK":
                    int limitWarningStock = -1;
                    try {
                        limitWarningStock = Integer.parseInt(cv);
                    } catch (NumberFormatException e) {
                    }
                    if (limitWarningStock >= 0) {
                        updateConfMap.put(ck, cv);
                    }
                    break;
            }
        });
        if (CollectionUtils.isEmpty(updateConfMap)) {
            log.warn("店铺管理:店铺设置:编辑[UID={},param={}]，无效操作:无效配置", currentUid, JsonUtils.toJson(param));
            return ResponseDto.failure(ErrorMapping.get("149001"));
        }
        boolean resultFlg = goblinStoreMgtService.updateStoreMgtConfig(currentUid, storeId, updateConfMap);
        return resultFlg ? ResponseDto.success() : ResponseDto.failure();
    }

    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "店铺管理:公告通知:列表")
    @PostMapping(value = {"notice/list"})
    public ResponseDto<PagedResult<GoblinStoreNoticeVo>> noticeList(@Valid @RequestBody GoblinStoreMgtNoticeFilterParam noticeFilterParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, noticeFilterParam.getStoreId())) {
            log.warn("店铺管理:公告通知:列表:无权查看该店铺[UID={},storeId={}]", currentUid, noticeFilterParam.getStoreId());
            return ResponseDto.success();
        }
        if (log.isDebugEnabled()) {
            log.debug("店铺管理:公告通知:列表[UID={},noticeFilterParam={}]", currentUid, JsonUtils.toJson(noticeFilterParam));
        }
        return ResponseDto.success(goblinStoreMgtNoticeService.pageList(noticeFilterParam));
    }

    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "店铺管理:公告通知:添加")
    @PostMapping(value = {"notice/add"})
    public ResponseDto<Object> noticeAdd(@Valid @RequestBody GoblinStoreMgtNoticeAddParam noticeAddParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, noticeAddParam.getStoreId())) {
            log.warn("店铺管理:公告通知:添加:无权操作该店铺[UID={},storeId={}]", currentUid, noticeAddParam.getStoreId());
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (log.isDebugEnabled()) {
            log.debug("店铺管理:公告通知:添加[UID={},noticeAddParam={}]", currentUid, JsonUtils.toJson(noticeAddParam));
        }
        if (noticeAddParam.getLongLasting().equals("0") && null == noticeAddParam.getCancellTime()) {
            return ResponseDto.failure(ErrorCode.HTTP_PARAM_ERROR.getCode(), "结束时间不能为空");
        }
        LocalDateTime now = LocalDateTime.now();

        GoblinStoreNoticeVo addStoreNoticeVo = GoblinStoreNoticeVo.getNew();
        addStoreNoticeVo.setStoreId(noticeAddParam.getStoreId());
        addStoreNoticeVo.setNoticeId(IDGenerator.nextMilliId());
        addStoreNoticeVo.setContent(noticeAddParam.getContent());
        addStoreNoticeVo.setReleaseTime(DateUtil.Formatter.yyyyMMddHHmmss.parse(noticeAddParam.getReleaseTime()));
        addStoreNoticeVo.setLongLasting(noticeAddParam.getLongLasting());
        if (noticeAddParam.getLongLasting().equals("0")) {
            addStoreNoticeVo.setCancellTime(DateUtil.Formatter.yyyyMMddHHmmss.parse(noticeAddParam.getCancellTime()));
        }
        addStoreNoticeVo.setStatus(addStoreNoticeVo.getReleaseTime().compareTo(now) > 0 ? "0" : "1");
        addStoreNoticeVo.setDelFlg("0");
        addStoreNoticeVo.setCreatedBy(currentUid);
        addStoreNoticeVo.setCreatedAt(now);

        goblinStoreMgtNoticeService.addSave(addStoreNoticeVo);
        return ResponseDto.success(addStoreNoticeVo.getNoticeId());
    }

    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "店铺管理:公告通知:编辑")
    @PostMapping(value = {"notice/edit"})
    public ResponseDto<Object> noticeEdit(@Valid @RequestBody GoblinStoreMgtNoticeAddParam noticeEditParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, noticeEditParam.getStoreId())) {
            log.warn("店铺管理:公告通知:编辑:无权操作该店铺[UID={},storeId={}]", currentUid, noticeEditParam.getStoreId());
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        List<GoblinStoreNoticeVo> noticeVos = goblinRedisUtils.getStoreNoticeVos(noticeEditParam.getStoreId(), LocalDateTime.now());
        if (CollectionUtils.isEmpty(noticeVos)) {
            log.warn("店铺管理:公告通知:编辑:无效操作，请先添加公告[UID={},noticeEditParam={}]", currentUid, JsonUtils.toJson(noticeEditParam));
            return ResponseDto.failure(ErrorMapping.get("149001"));
        }
        if (log.isDebugEnabled()) {
            log.debug("店铺管理:公告通知:编辑[UID={},noticeEditParam={}]", currentUid, JsonUtils.toJson(noticeEditParam));
        }
        Optional<GoblinStoreNoticeVo> optional = noticeVos.stream().filter(r -> r.getNoticeId().equals(noticeEditParam.getNoticeId())).findAny();
        if (!optional.isPresent() || optional.get().getStatus().equals("1")) {
            log.warn("店铺管理:公告通知:编辑:无效操作，公告已发布或不存在[UID={},noticeEditParam={}]", currentUid, JsonUtils.toJson(noticeEditParam));
            return ResponseDto.failure(ErrorMapping.get("149001"));
        }
        LocalDateTime now = LocalDateTime.now();

        GoblinStoreNoticeVo updateStoreNoticeVo = GoblinStoreNoticeVo.getNew();
        updateStoreNoticeVo.setStoreId(noticeEditParam.getStoreId());
        updateStoreNoticeVo.setNoticeId(noticeEditParam.getNoticeId());
        updateStoreNoticeVo.setContent(noticeEditParam.getContent());
        updateStoreNoticeVo.setReleaseTime(DateUtil.Formatter.yyyyMMddHHmmss.parse(noticeEditParam.getReleaseTime()));
        updateStoreNoticeVo.setLongLasting(noticeEditParam.getLongLasting());
        if (noticeEditParam.getLongLasting().equals("0")) {
            updateStoreNoticeVo.setCancellTime(DateUtil.Formatter.yyyyMMddHHmmss.parse(noticeEditParam.getCancellTime()));
        }
        updateStoreNoticeVo.setStatus(updateStoreNoticeVo.getReleaseTime().compareTo(now) > 0 ? "0" : "1");
        updateStoreNoticeVo.setUpdatedBy(currentUid);
        updateStoreNoticeVo.setUpdatedAt(now);

        boolean resultFlg = goblinStoreMgtNoticeService.editSave(updateStoreNoticeVo);
        return resultFlg ? ResponseDto.success() : ResponseDto.failure();
    }

    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "店铺管理:公告通知:管理")
    @PostMapping(value = {"notice/operate"})
    public ResponseDto<Object> noticeOperate(@Valid @RequestBody GoblinStoreMgtNoticeActionParam noticeActionParam) {
        String currentUid = CurrentUtil.getCurrentUid();
        if (!goblinRedisUtils.hasStoreId(currentUid, noticeActionParam.getStoreId())) {
            log.warn("店铺管理:公告通知:管理:无权操作该店铺[UID={},storeId={}]", currentUid, noticeActionParam.getStoreId());
            return ResponseDto.failure(ErrorMapping.get("149002"));
        }
        if (log.isDebugEnabled()) {
            log.debug("店铺管理:公告通知:管理[UID={},noticeActionParam={}]", currentUid, JsonUtils.toJson(noticeActionParam));
        }
        boolean operateResultFlg;
        switch (noticeActionParam.getAction()) {
            case "RELEASE":
                operateResultFlg = goblinStoreMgtNoticeService.releaseProcessing(currentUid, noticeActionParam.getStoreId(), noticeActionParam.getNoticeIdList());
                break;
            case "REMOVE":
                operateResultFlg = goblinStoreMgtNoticeService.removeProcessing(currentUid, noticeActionParam.getStoreId(), noticeActionParam.getNoticeIdList());
                break;
            default:
                log.warn("Invalid operation[UID={},noticeActionParam={}]", currentUid, JsonUtils.toJson(noticeActionParam));
                return ResponseDto.failure(ErrorMapping.get("149001"));
        }
        return operateResultFlg ? ResponseDto.success() : ResponseDto.failure();
    }
}
