package com.neusoft.smart.pos.member.controller;

import com.neusoft.smart.pos.dto.member.request.*;
import com.neusoft.smart.pos.dto.member.response.DetailedMemberResponse;
import com.neusoft.smart.pos.dto.member.response.GetMembersResponse;
import com.neusoft.smart.pos.dto.member.response.MemberResponse;
import com.neusoft.smart.pos.dto.promotion.bean.CalculateBean;
import com.neusoft.smart.pos.framework.dto.ResponseData;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.member.constants.MemberErrorCode;
import com.neusoft.smart.pos.member.persistent.domain.Member;
import com.neusoft.smart.pos.member.persistent.domain.MemberLevelPolicy;
import com.neusoft.smart.pos.member.service.Member4CanteenService;
import com.neusoft.smart.pos.member.service.MemberBusinessService;
import com.neusoft.smart.pos.member.service.MemberLevelPolicyService;
import com.neusoft.smart.pos.member.service.MemberService;
import com.neusoft.smart.pos.redis.bean.DeviceInfo;
import com.neusoft.smart.pos.utils.PosDeviceRedisUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Api(value = "会员管理restful接口", description = "会员管理restful接口")
@RestController
@Validated
public class MemberController {
    
    @Autowired
    MemberService memberService;
    
    @Autowired
    Member4CanteenService member4CanteenService;

    @Autowired
    MemberLevelPolicyService memberLevelPolicyService;
    
    @Autowired
    private MemberBusinessService memberBusinessService;
    
    @ApiOperation(value = "get members")
    @GetMapping("/members")
    public ResponseData<GetMembersResponse> getMemberList(@Validated @ModelAttribute GetMembersRequest request) {
        switch (memberBusinessService.getBusiness()) {
            case 1://普通会员卡
                return new ResponseData<>(memberService.getMembers(request));
            case 2://食堂会员卡
                return new ResponseData<>(member4CanteenService.getMembers(request));
            default:
                return new ResponseData<>(memberService.getMembers(request));
        }
        
    }
    
    @ApiOperation(value = "get store member number")
    @GetMapping("/members/store/num")
    public ResponseData<Integer> getStoreMemberNum(
            @RequestParam(value = "org", defaultValue = "-1") Integer org,
            @RequestParam(value = "store", defaultValue = "-1") Integer store) {
        return new ResponseData<>(memberService.getStoreMemberNum(org, store));
    }
    
    @ApiOperation(value = "get member")
    @GetMapping(value = {"/members/{id}", "/members/{id}/{cardId}"})
    public ResponseData<DetailedMemberResponse> getMemberById(@PathVariable Integer id, @PathVariable(required = false) Integer cardId) {
        switch (memberBusinessService.getBusiness()) {
            case 1://普通会员卡
                return new ResponseData<>(memberService.getMemberById(id));
            case 2://食堂会员卡
                return new ResponseData<>(member4CanteenService.getMemberById(id, cardId, false));
            default:
                return new ResponseData<>(memberService.getMemberById(id));
        }
        
    }
    
    @ApiOperation(value = "get single member by condition")
    @GetMapping("/members/single")
    public ResponseData<DetailedMemberResponse> getMemberByCondition(
            @RequestParam(value = "mobile", defaultValue = "", required = false) String mobile,
            @RequestParam(value = "cardNum", defaultValue = "", required = false) String cardNum,
            @RequestParam(value = "cardHardwareNum", defaultValue = "", required = false) String cardHardwareNum,
            @RequestParam(value = "org", defaultValue = "-1", required = false) Integer org,
            @RequestParam(value = "store", defaultValue = "-1", required = false) Integer store) {
        switch (memberBusinessService.getBusiness(org)) {
            case 1://普通会员卡
                return new ResponseData<>(memberService.getSingleMember(mobile, cardNum, cardHardwareNum, org, store));
            case 2://食堂会员卡
                return new ResponseData<>(member4CanteenService.getSingleMember(mobile, cardNum, org, store));
            default:
                return new ResponseData<>(memberService.getSingleMember(mobile, cardNum, cardHardwareNum,  org, store));
        }
        
    }

    @ApiOperation(value = "calculate order")
    @PostMapping("/member/calculate-member-bonus")
    ResponseData<CalculateBean> calculateByMemberLevelPolicy(
            @RequestParam(value = "mobile", defaultValue = "", required = false) String mobile,
            @RequestParam(value = "cardNum", defaultValue = "", required = false) String cardNum,
            @RequestParam(value = "cardHardwareNum", defaultValue = "", required = false) String cardHardwareNum,
            @RequestParam(value = "org", defaultValue = "-1", required = false) Integer org,
            @RequestParam(value = "store", defaultValue = "-1", required = false) Integer store,
            @RequestParam(value = "calculateBean", defaultValue = "-1", required = true) CalculateBean bean) {
        DetailedMemberResponse detailedMember = null;

        switch (memberBusinessService.getBusiness(org)) {
            case 1://普通会员卡
                detailedMember = memberService.getSingleMember(mobile, cardNum, cardHardwareNum, org, store);
                break;
            case 2://食堂会员卡
                detailedMember = member4CanteenService.getSingleMember(mobile, cardNum, org, store);
                break;
            default:
                detailedMember = memberService.getSingleMember(mobile, cardNum, cardHardwareNum, org, store);
        }

        return new ResponseData<>(memberLevelPolicyService.calculate(detailedMember, bean));
    }
    @ApiOperation(value = "check-and-upgrade")
    @PostMapping("/member/check-and-upgrade")
    ResponseData<Integer> checkAndUpgradeMemberLevel(
            @RequestParam(value = "mobile", defaultValue = "", required = false) String mobile,
            @RequestParam(value = "cardNum", defaultValue = "", required = false) String cardNum,
            @RequestParam(value = "cardHardwareNum", defaultValue = "", required = false) String cardHardwareNum,
            @RequestParam(value = "org", defaultValue = "-1", required = false) Integer org,
            @RequestParam(value = "store", defaultValue = "-1", required = false) Integer store,
            @RequestParam(value = "calculateBean", defaultValue = "-1", required = true) CheckMemberLevelRequest request) {
        DetailedMemberResponse detailedMember = null;

        switch (memberBusinessService.getBusiness(org)) {
            case 1://普通会员卡
                detailedMember = memberService.getSingleMember(mobile, cardNum, cardHardwareNum, org, store);
                break;
            case 2://食堂会员卡
                detailedMember = member4CanteenService.getSingleMember(mobile, cardNum, org, store);
                break;
            default:
                detailedMember = memberService.getSingleMember(mobile, cardNum, cardHardwareNum, org, store);
        }
        MemberLevelPolicy currentPolicy = memberLevelPolicyService.getMemberLevelPolicyById(detailedMember.getMemberLevelId());
        List<MemberLevelPolicy> policies = memberLevelPolicyService.getMemberLevelPoliciesByOrgStore(org, store);
        policies.removeIf(o -> o.getLevelNumber() <= currentPolicy.getLevelNumber());

        MemberLevelPolicy newPolicy = currentPolicy;
        for (MemberLevelPolicy policy : policies
        ) {
            if (policy.getLevelNumber() > newPolicy.getLevelNumber() && memberLevelPolicyService.checkMemberMatchLevel(policy, request)) {
                newPolicy = policy;
            }
        }

        memberService.updateMemberLevelId(newPolicy.getId());

        return new ResponseData<>(newPolicy.getId());
    }


    @ApiOperation(value = "create member")
    @PostMapping("/members") //TODO 创建店铺和卡的对应关系;创建卡兑换策略 PosRegisterMemberRequest和CreateMemberRequest需要加参数(见gateway中的MemberService.java)
    public ResponseData<DetailedMemberResponse> addMember(@RequestBody CreateMemberRequest request) {
        switch (memberBusinessService.getBusiness(request.getOrg())) {
            case 1://普通会员卡
                return new ResponseData<>(memberService.createMember(request));
            case 2://食堂会员卡
                return new ResponseData<>(member4CanteenService.createMember(request));
            default:
                return new ResponseData<>(memberService.createMember(request));
        }
    }
    
    @ApiOperation(value = "update member")
    @PatchMapping("/members")
    public ResponseData<MemberResponse> updateMember(@RequestBody UpdateMemberRequest request) {
        switch (memberBusinessService.getBusiness()) {
            case 1://普通会员卡
                return new ResponseData<>(memberService.updateMember(request));
            case 2://食堂会员卡
                return new ResponseData<>(member4CanteenService.updateMember(request));
            default:
                return new ResponseData<>(memberService.updateMember(request));
        }
    }
    
    @ApiOperation(value = "find member from pos")
    @GetMapping("/members/pos/{snCode}")
    public ResponseData<DetailedMemberResponse> getMemberByPos(@PathVariable String snCode, @ModelAttribute PosGetMemberRequest request) {
        DeviceInfo deviceInfo = PosDeviceRedisUtils.getDeviceInfoBySerialNo(snCode);
        
        if (null == deviceInfo) {
            throw new BusinessCommonException(MemberErrorCode.DEVICE_INFO_NOT_FOUND);
        }
        
        GetMembersRequest r = new GetMembersRequest();
        r.setStore(deviceInfo.getStoreId());
        
        if (StringUtils.isEmpty(request.getCardNum()) && StringUtils.isEmpty(request.getMobile())) {
            throw new BusinessCommonException(MemberErrorCode.NO_CARD_NUM_OR_MOBILE_PROVIDED);
        }
        
        r.setCardNum(request.getCardNum());
        r.setMobile(request.getMobile());
        GetMembersResponse result;
        
        switch (memberBusinessService.getBusiness(deviceInfo.getOrganizationId())) {
            case 1://普通会员卡
                result = memberService.getMembers(r);
                break;
            case 2://食堂会员卡
                result = memberService.getMembers(r);
                break;
            default:
                result = memberService.getMembers(r);
        }
        
        if (result.getTotal() != 0) {
            return new ResponseData<>(result.getData().get(0));
        }
        
        return new ResponseData<>(null);
    }
    
    @ApiOperation(value = "find member detail by  hid code in the card")
    @GetMapping("/members/hid/{hidCode}")
    public ResponseData<DetailedMemberResponse> getDetailByHidCode(@PathVariable String hidCode) {
        return new ResponseData<>(member4CanteenService.getDetailByHidCode(hidCode));
    }
    
    @ApiOperation(value = "nullify member")
    @PatchMapping("/members/nullify/{hidCode}")
    public ResponseData<?> nullifyMember(@PathVariable String hidCode) {
        member4CanteenService.nullifyMember(hidCode);
        return new ResponseData<>();
    }
    
    @ApiOperation(value = "h5 页面登录会员后返回跳转url")
    @GetMapping("/member/h5")
    public ResponseData<String> getMember4H5(String mobile, String password, String businessCode) {
        return new ResponseData<>(member4CanteenService.getSingleMemberUrl4H5(mobile, password, businessCode));
    }
}
