package com.hzs.member.base.controller.api;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.collection.CollectionUtil;
import com.hzs.common.core.annotation.Log;
import com.hzs.common.core.annotation.RepeatSubmitSimple;
import com.hzs.common.core.config.BdConfig;
import com.hzs.common.core.constant.CacheConstants;
import com.hzs.common.core.constant.TableNameConstants;
import com.hzs.common.core.constant.msg.CommonMsgConstants;
import com.hzs.common.core.constant.msg.ConfigMsgConstants;
import com.hzs.common.core.constant.msg.MemberMsgConstants;
import com.hzs.common.core.domain.FileResult;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.service.RedisService;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.core.utils.uuid.IdUtils;
import com.hzs.common.core.web.controller.BaseController;
import com.hzs.common.core.web.domain.AjaxResult;
import com.hzs.common.core.web.page.TableDataInfo;
import com.hzs.common.domain.member.achieve.CuMemberRetailDetail;
import com.hzs.common.domain.member.achieve.CuMemberSettlePeriod;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.common.domain.member.detail.CuMemberChangeLog;
import com.hzs.common.domain.member.ext.CuMemberExt;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.common.util.TransactionUtils;
import com.hzs.member.achieve.service.ICuMemberSettlePeriodService;
import com.hzs.member.base.param.ForgetPasswordParam;
import com.hzs.member.base.param.MemberDataParam;
import com.hzs.member.base.service.ICuMemberRetailService;
import com.hzs.member.base.service.ICuMemberService;
import com.hzs.member.base.service.IMemberInfoService;
import com.hzs.common.core.utils.UploadFileUtil;
import com.hzs.member.base.vo.*;
import com.hzs.member.sms.service.IApiAliSmsService;
import com.hzs.system.config.IGradeServiceApi;
import com.hzs.system.config.dto.GradeDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 会员控制器
 */
@Slf4j
@RequestMapping("/api/member")
@RestController
public class ApiMemberController extends BaseController {

    @Autowired
    private IMemberInfoService iMemberInfoService;
    @Autowired
    private ICuMemberService iCuMemberService;
    @Autowired
    private IApiAliSmsService iApiAliSmsService;
    @Autowired
    private ICuMemberRetailService iCuMemberRetailService;
    @Autowired
    private ICuMemberSettlePeriodService iCuMemberSettlePeriodService;


    @Autowired
    private RedisService redisService;

    @DubboReference
    IGradeServiceApi iGradeServiceApi;

    /**
     * 更新个人资料（昵称）
     *
     * @param param
     * @return
     */
    @PutMapping("/update-data")
    public AjaxResult updateData(@RequestBody MemberDataParam param) {
        if (StringUtils.isEmpty(param.getNickName())) {
            return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.MISSING_PARAM));
        }
        Long memberId = SecurityUtils.getUserId();
        CuMember member = iCuMemberService.getMemberById(memberId);
        if (null == member) {
            // 会员不存在
            return AjaxResult.error(TransactionUtils.getContent(MemberMsgConstants.MEMBER_NOT_EXITS));
        }

        // 会员修改信息
        CuMember cuMember = new CuMember();
        cuMember.setPkId(memberId);
        cuMember.setNickName(param.getNickName());
        cuMember.setPkModified(memberId);
        cuMember.setModifiedTime(new Date());
        // 会员修改记录信息
        CuMemberChangeLog cuMemberChangeLog = CuMemberChangeLog.builder()
                .pkMember(memberId)
                .changeType(EMemberChangeType.NICK_NAME.getValue())
                .changeFront(member.getNickName())
                .changeAfter(param.getNickName())
                .build();
        iMemberInfoService.updateMemberInfo(cuMember, Collections.singletonList(cuMemberChangeLog));
        return AjaxResult.success();
    }

    /**
     * 更新头像
     *
     * @param file
     * @return
     */
    @PostMapping("/update-head")
    public AjaxResult updateHead(MultipartFile file) {
        if (null == file) {
            return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.MISSING_PARAM));
        }
        Long memberId = SecurityUtils.getUserId();
        CuMember member = iCuMemberService.getMemberById(memberId);
        if (null == member) {
            // 会员不存在
            return AjaxResult.error(TransactionUtils.getContent(MemberMsgConstants.MEMBER_NOT_EXITS));
        }

        FileResult fileResult = UploadFileUtil.upload(file, "head");
        if (null != fileResult) {
            // 会员修改信息
            CuMember cuMember = new CuMember();
            cuMember.setPkId(memberId);
            cuMember.setHeadPath(fileResult.getUrl());
            cuMember.setPkModified(memberId);
            cuMember.setModifiedTime(new Date());
            // 会员修改记录信息
            CuMemberChangeLog cuMemberChangeLog = CuMemberChangeLog.builder()
                    .pkMember(memberId)
                    .changeType(EMemberChangeType.HEAD.getValue())
                    .changeFront(member.getHeadPath())
                    .changeAfter(fileResult.getUrl())
                    .build();
            iMemberInfoService.updateMemberInfo(cuMember, Collections.singletonList(cuMemberChangeLog));
            return AjaxResult.success(fileResult);
        }
        return AjaxResult.error();
    }

    /**
     * 更新密码
     *
     * @param param
     * @return
     */
    @PutMapping("/update-password")
    public AjaxResult updatePassword(@RequestBody MemberDataParam param) {
        if (StringUtils.isEmpty(param.getOldPassword())
                || StringUtils.isAllEmpty(param.getLoginPassword(), param.getPayPassword())) {
            return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.MISSING_PARAM));
        }
        Long memberId = SecurityUtils.getUserId();
        CuMember member = iCuMemberService.getMemberById(memberId);
        if (null == member) {
            // 会员不存在
            return AjaxResult.error(TransactionUtils.getContent(MemberMsgConstants.MEMBER_NOT_EXITS));
        }

        if (StringUtils.isNotEmpty(param.getLoginPassword())) {
            // 修改登录密码
            if (SecurityUtils.matchesPassword(param.getOldPassword(), member.getLoginPwd())) {
                // 会员修改信息
                CuMember cuMember = new CuMember();
                cuMember.setPkId(memberId);
                cuMember.setLoginPwd(SecurityUtils.encryptPassword(param.getLoginPassword()));
                cuMember.setLoginPassword(param.getLoginPassword());
                cuMember.setPkModified(memberId);
                cuMember.setModifiedTime(new Date());
                // 会员修改记录信息
                CuMemberChangeLog cuMemberChangeLog = CuMemberChangeLog.builder()
                        .pkMember(memberId)
                        .changeType(EMemberChangeType.LOGIN_PWD.getValue())
                        .changeFront(member.getLoginPassword())
                        .changeAfter(param.getLoginPassword())
                        .build();
                iMemberInfoService.updateMemberInfo(cuMember, Collections.singletonList(cuMemberChangeLog));
                return AjaxResult.success();
            } else {
                // 旧密码错误
                return AjaxResult.error(TransactionUtils.getContent(MemberMsgConstants.PASSWORD_ERROR));
            }
        } else if (StringUtils.isNotEmpty(param.getPayPassword())) {
            // 修改支付密码
            if (SecurityUtils.matchesPassword(param.getOldPassword(), member.getPayPwd())) {
                // 会员修改信息
                CuMember cuMember = new CuMember();
                cuMember.setPkId(memberId);
                cuMember.setPayPwd(SecurityUtils.encryptPassword(param.getPayPassword()));
                cuMember.setPayPassword(param.getPayPassword());
                cuMember.setPkModified(memberId);
                cuMember.setModifiedTime(new Date());
                // 会员修改记录信息
                CuMemberChangeLog cuMemberChangeLog = CuMemberChangeLog.builder()
                        .pkMember(memberId)
                        .changeType(EMemberChangeType.PAY_PWD.getValue())
                        .changeFront(member.getPayPassword())
                        .changeAfter(param.getPayPassword())
                        .build();
                iMemberInfoService.updateMemberInfo(cuMember, Collections.singletonList(cuMemberChangeLog));
                return AjaxResult.success();
            } else {
                // 旧密码错误
                return AjaxResult.error(TransactionUtils.getContent(MemberMsgConstants.PASSWORD_ERROR));
            }
        }
        return AjaxResult.error();
    }

    /**
     * 更新邮箱
     *
     * @param param
     * @return
     */
    @Deprecated
    @PutMapping("/update-email")
    public AjaxResult updateEmail(@RequestBody MemberDataParam param) {
        return AjaxResult.success();
    }

    /**
     * 忘记密码更新
     *
     * @param param
     * @return
     */
    @RepeatSubmitSimple
    @PutMapping("/forget-password")
    public AjaxResult forgetPassword(@Valid @RequestBody ForgetPasswordParam param) {
        String loginPassword = param.getLoginPassword();

        List<CuMemberExt> cuMemberList = iCuMemberService.listMemberByPhone(param.getPhone());
        if (CollectionUtil.isEmpty(cuMemberList)) {
            return AjaxResult.error("会员联系方式不存在");
        }

        CuMemberExt cuMemberExt = null;
        for (CuMemberExt tmpMember : cuMemberList) {
            if (tmpMember.getMemberCode().equals(param.getMemberCode())) {
                cuMemberExt = tmpMember;
            }
        }
        if (null == cuMemberExt) {
            return AjaxResult.error("会员信息不存在");
        }
        Long memberId = cuMemberExt.getPkId();

        // 校验短信验证码是否有效
        String checkSmsStr = iApiAliSmsService.checkRecoverCode(param.getPhone(), param.getCode(), memberId);
        if (null != checkSmsStr) {
            return AjaxResult.error(checkSmsStr);
        }

        // 会员修改信息
        CuMember cuMember = new CuMember();
        cuMember.setPkId(memberId);
        cuMember.setLoginPwd(SecurityUtils.encryptPassword(loginPassword));
        cuMember.setLoginPassword(loginPassword);
        cuMember.setPkModified(memberId);
        cuMember.setModifiedTime(new Date());
        // 会员修改记录信息
        CuMemberChangeLog cuMemberChangeLog = CuMemberChangeLog.builder()
                .pkMember(memberId)
                .changeType(EMemberChangeType.LOGIN_PWD.getValue())
                .changeFront(cuMemberExt.getLoginPassword())
                .changeAfter(loginPassword)
                .build();
        iMemberInfoService.updateMemberInfo(cuMember, Collections.singletonList(cuMemberChangeLog));

        return AjaxResult.success();
    }

    /**
     * 忘记支付密码更新
     *
     * @param param 入参
     * @return
     */
    @RepeatSubmitSimple
    @PutMapping("/forget-pay-password")
    public AjaxResult forgetPayPassword(@RequestBody MemberDataParam param) {
        if (StringUtils.isAnyEmpty(param.getCode(), param.getPayPassword())) {
            return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.MISSING_PARAM));
        }
        String payPassword = param.getPayPassword();
        CuMemberExt cuMemberExt = iCuMemberService.getMemberById(SecurityUtils.getUserId());
        if (null == cuMemberExt) {
            // 会员不存在
            return AjaxResult.error(TransactionUtils.getContent(ConfigMsgConstants.MEMBER_NOT_EXIST));
        }
        Long memberId = cuMemberExt.getPkId();

        // 校验短信验证码是否有效
        String checkSmsStr = iApiAliSmsService.checkPayPasswordCode(cuMemberExt.getPhone(), param.getCode(), memberId);
        if (null != checkSmsStr) {
            return AjaxResult.error(checkSmsStr);
        }

        // 会员修改信息
        CuMember cuMember = new CuMember();
        cuMember.setPkId(memberId);
        cuMember.setPayPwd(SecurityUtils.encryptPassword(payPassword));
        cuMember.setPayPassword(payPassword);
        cuMember.setPkModified(memberId);
        cuMember.setModifiedTime(new Date());
        // 会员修改记录信息
        CuMemberChangeLog cuMemberChangeLog = CuMemberChangeLog.builder()
                .pkMember(memberId)
                .changeType(EMemberChangeType.PAY_PWD.getValue())
                .changeFront(cuMemberExt.getPayPassword())
                .changeAfter(payPassword)
                .build();
        iMemberInfoService.updateMemberInfo(cuMember, Collections.singletonList(cuMemberChangeLog));


        return AjaxResult.success();
    }

    /**
     * 查询会员注册信息
     *
     * @param orderCode 订单编号
     * @return
     */
    @RepeatSubmitSimple
    @GetMapping("/register-order/{orderCode}")
    public AjaxResult registerOrder(@PathVariable("orderCode") String orderCode) {
        CuMemberExt cuMemberExt = iCuMemberService.queryRegisterOrder(orderCode, SecurityUtils.getUserId());
        if (null == cuMemberExt) {
            return AjaxResult.error("注册会员失败，请联系客服处理");
        }

        return AjaxResult.success(MemberShare.builder()
                .memberName(cuMemberExt.getMemberName())
                .memberCode(cuMemberExt.getMemberCode())
                .phone(cuMemberExt.getPhone())
                .loginPassword(cuMemberExt.getLoginPassword())
                .payPassword(cuMemberExt.getPayPassword())
                .build());
    }

    /**
     * 会员 推荐列表（直推列表）
     */
    @GetMapping("parent-list")
    public TableDataInfo parentList(String memberCode, String memberName, Date startCreateTime, Date endCreateTime, String memberInfo) {
        Long memberId = SecurityUtils.getUserId();
        if (endCreateTime != null) {
            endCreateTime = DateUtils.getEndTime(endCreateTime);
        }

        startPage();
        List<ParentMemberVo> list = iCuMemberService.parentList(memberId, memberCode, memberName, startCreateTime, endCreateTime, memberInfo);

        if (CollectionUtil.isNotEmpty(list)) {
            R<List<GradeDTO>> gradeDate = iGradeServiceApi.findAll();
            List<GradeDTO> gradeList = gradeDate.getData();

            for (ParentMemberVo cuMember : list) {
                cuMember.setMemberCode(cuMember.getMemberCode());
                cuMember.setMemberName(cuMember.getMemberName());

                for (GradeDTO gradeDTO : gradeList) {
                    if (gradeDTO.getPkId().equals(cuMember.getPkRegisterGrade())) {
                        cuMember.setPkRegisterGradeStr(gradeDTO.getGradeName());
                    }
                }
                for (GradeDTO gradeDTO : gradeList) {
                    if (gradeDTO.getPkId().equals(cuMember.getPkSettleGrade())) {
                        cuMember.setPkSettleGradeStr(gradeDTO.getGradeName());
                    }
                }
            }
        }
        return getDataTable(list);
    }


    /**
     * 查询推荐人编号 -- 188分享注册
     *
     * @param pkParent 推荐人（加密）
     * @return
     */
    @GetMapping("/fans-convert-code/{pkParent}")
    public AjaxResult fansConvertCode(@PathVariable("pkParent") String pkParent) {
        // 验证必输项
        if (pkParent == null) {
            return AjaxResult.error(MemberMsgConstants.REQUIRED_NOT_EMPTY);
        }
        CuMember cuMember = iCuMemberService.getMemberById(Long.parseLong(new String(Base64Decoder.decode(pkParent))));
        if (null != cuMember) {
            return AjaxResult.success("", cuMember.getMemberCode());
        }
        return AjaxResult.error();
    }

    /**
     * 根据订单查询会员信息 -- 188分享注册
     *
     * @param orderCode 订单编号
     * @return
     */
//    @RepeatSubmitSimple(intervalTime = 2L)
    @GetMapping("/fans-order/{orderCode}")
    public AjaxResult fansOrder(@PathVariable("orderCode") String orderCode) {
        CuMemberExt cuMemberExt = iCuMemberService.queryFansOrder(orderCode);
        if (null == cuMemberExt) {
            return AjaxResult.error("注册会员失败，请联系客服处理");
        }
        // 自动登录 uuid 标记
        String uuid = IdUtils.simpleUUID();
        // 根据会员编号放一个登录 uuid 做为自动登录校验使用（120分钟有效）
        redisService.setCacheObject(CacheConstants.AUTO_LOGIN + cuMemberExt.getMemberCode(), uuid, CacheConstants.LOGIN_TOKEN_REFRESH_TIME * 2, TimeUnit.MINUTES);


        return AjaxResult.success(MemberShare.builder()
                .memberName(cuMemberExt.getMemberName())
                .memberCode(cuMemberExt.getMemberCode())
                .phone(cuMemberExt.getPhone())
                .loginPassword(cuMemberExt.getLoginPassword())
                .payPassword(cuMemberExt.getPayPassword())
                .urlAddress(BdConfig.getPc())
//                .gzh(BdConfig.getGzh())
//                .ios(BdConfig.getIos())
//                .android(BdConfig.getAndroid())
                .uuid(uuid)
                .build());
    }
    /**
     *
     * @return
     */
    @Log(module = EOperationModule.MEMBER_POINT, business = EOperationBusiness.MEMBER_POINT, method = EOperationMethod.SELECT)
    @GetMapping("/member-point")
    public AjaxResult memberPoint() {
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            log.error("用户登录信息错误");
            return AjaxResult.error(CommonMsgConstants.MISSING_PARAM);
        }
        // 获取当前时间 -1 天
        String yesterday  = LocalDate.now().minusDays(1).format((DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        // 查询相关日结表
        CuMemberSettlePeriod csPeriod = iCuMemberSettlePeriodService.getCuMemberSettlePeriodByDate(yesterday);
        log.info("会员结算表信息{}",csPeriod);
        String settleTableName = TableNameConstants.CU_MEMBER_RETAIL_RANGE + csPeriod.getPkId();
        String settleDetailTableName = TableNameConstants.CU_MEMBER_RETAIL_RANGE_DETAIL + csPeriod.getPkId();
        log.info("会员结算表名称{}{}",settleTableName,settleDetailTableName);
        // 校验当前日结表是否存在
        Integer isFind = iCuMemberRetailService.getFindCuMemberRetailDetail(settleTableName);
        if (isFind == null || isFind != 1) {
            log.error("当前表名不存在{}",settleTableName);
            return AjaxResult.error("数据查询错误,请联系客服处理");
        }
        MemberPointVO memberPointVO = iCuMemberRetailService.getMemberPointByUserId(settleDetailTableName,settleTableName,userId);
        if (memberPointVO == null) {
            return AjaxResult.success();
        }
        memberPointVO.setMemberSettlePeriod(csPeriod.getSettleDate());
        startPage();
        return AjaxResult.success(memberPointVO);
    }
}
