
package com.tmerclub.cloud.payment.controller.app;

import cn.hutool.core.util.PhoneUtil;
import com.tmerclub.cloud.api.auth.bo.UidInfoBO;
import com.tmerclub.cloud.api.auth.feign.AuthSocialFeignClient;
import com.tmerclub.cloud.api.biz.feign.NotifyFeignClient;
import com.tmerclub.cloud.api.payment.allinpay.member.resp.BindCard;
import com.tmerclub.cloud.api.user.dto.UserExtensionDTO;
import com.tmerclub.cloud.api.user.feign.UserExtensionFeignClient;
import com.tmerclub.cloud.common.constant.AllinpayConstant;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.payment.allinpay.constant.AllinpayNoticeUrl;
import com.tmerclub.cloud.payment.allinpay.member.resp.*;
import com.tmerclub.cloud.payment.dto.*;
import com.tmerclub.cloud.payment.allinpay.member.resp.*;
import com.tmerclub.cloud.payment.dto.*;
import com.tmerclub.cloud.payment.service.AllinpayService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Objects;

/**
 * @author lanhai
 */
@Tag(name = "通联支付-会员接口(用户端)")
@RestController("appAllinpayMemberController")
@RequestMapping("/allinpay/member")
public class AllinpayMemberController {

    @Autowired
    private AllinpayService allinpayService;

    @DubboReference
    private NotifyFeignClient notifyFeignClient;

    @DubboReference
    private AuthSocialFeignClient authSocialFeignClient;

    @DubboReference
    private UserExtensionFeignClient userExtensionFeignClient;

    @Value("${application.domainUrl}")
    private String domainUrl;

    @GetMapping("/getMemberInfo")
    @Operation(summary = "获取个人会员信息", description = "获取个人会员信息")
    public ServerResponseEntity<UserInfo> getMemberInfo() {
        String bizUserId = String.valueOf(AuthUserContext.get().getUserId());
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        userInfo.setIdentityCardNo(null);
        userInfo.setName(null);
        userInfo.setPhone(ObjectUtils.isEmpty(userInfo.getPhone()) ? null : PhoneUtil.hideBetween(userInfo.getPhone()).toString());
        // 同时也查询用户是否绑定支付标识
        QueryBindAcctResp queryBindAcctResp = allinpayService.queryBindAcct(bizUserId);
        userInfo.setIsBindPayAcct(!CollectionUtils.isEmpty(queryBindAcctResp.getAcctInfoList()));
        return ServerResponseEntity.success(userInfo);
    }

    @PostMapping("/setRealName")
    @Operation(summary = "个人实名验证", description = "个人实名验证")
    public ServerResponseEntity<Void> setRealName(@RequestBody SetRealNameBySmsCodeDTO setRealNameBySmsCodeDTO) {
        UserExtensionDTO userExtensionDTO = new UserExtensionDTO();
        // 实名认证
        Long userId = AuthUserContext.get().getUserId();
        SetRealNameDTO setRealNameDTO = new SetRealNameDTO();
        BeanUtils.copyProperties(setRealNameBySmsCodeDTO, setRealNameDTO);
        allinpayService.setRealName(userId, setRealNameDTO);
        // 更新用户拓展信息
        userExtensionDTO.setUserId(userId);
        userExtensionDTO.setAllinpayRealNameSet(1);
        userExtensionFeignClient.updateExtension(userExtensionDTO);
        return ServerResponseEntity.success();
    }

    @PostMapping("/setPayPwd")
    @Operation(summary = "设置支付密码", description = "设置支付密码")
    public ServerResponseEntity<String> setPayPwd(@RequestBody SetPayPwdDTO setPayPwdDTO) {
        Long userId = AuthUserContext.get().getUserId();
        // 查询用户信息，补充用户姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(userId.toString());
        setPayPwdDTO.setName(userInfo.getName());
        setPayPwdDTO.setIdentityNo(userInfo.getIdentityCardNo());
        setPayPwdDTO.setPhone(userInfo.getPhone());
        String backUrl = domainUrl + AllinpayNoticeUrl.SET_PAY_PWD;
        // 返回通联url
        String url = allinpayService.setPayPwd(userId, backUrl, setPayPwdDTO);
        return ServerResponseEntity.success(url);
    }

    @PutMapping("/updatePayPwd")
    @Operation(summary = "修改支付密码", description = "修改支付密码")
    public ServerResponseEntity<String> updatePayPwd(@RequestBody SetPayPwdDTO setPayPwdDTO) {
        Long userId = AuthUserContext.get().getUserId();
        // 查询用户信息，补充用户姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(userId.toString());
        setPayPwdDTO.setName(userInfo.getName());
        setPayPwdDTO.setIdentityNo(userInfo.getIdentityCardNo());
        setPayPwdDTO.setPhone(userInfo.getPhone());
        String backUrl = domainUrl + AllinpayNoticeUrl.UPDATE_PAY_PWD;
        // 返回通联url
        String url = allinpayService.updatePayPwd(userId, backUrl, setPayPwdDTO);
        return ServerResponseEntity.success(url);
    }

    @PutMapping("/resetPayPwd")
    @Operation(summary = "重置支付密码", description = "重置支付密码")
    public ServerResponseEntity<String> resetPayPwd(@RequestBody SetPayPwdDTO setPayPwdDTO) {
        Long userId = AuthUserContext.get().getUserId();
        // 查询用户信息，补充用户姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(userId.toString());
        setPayPwdDTO.setName(userInfo.getName());
        setPayPwdDTO.setIdentityNo(userInfo.getIdentityCardNo());
        setPayPwdDTO.setPhone(userInfo.getPhone());
        String backUrl = domainUrl + AllinpayNoticeUrl.RESET_PAY_PWD;
        // 返回通联url
        String url = allinpayService.resetPayPwd(userId, backUrl, setPayPwdDTO);
        return ServerResponseEntity.success(url);
    }

    @PutMapping("/updatePhoneByPayPwd")
    @Operation(summary = "修改绑定手机(返回通联页面url)", description = "仅限个人会员")
    public ServerResponseEntity<String> updatePhoneByPayPwd(@RequestBody UpdatePhoneByPayPwdDTO updatePhoneByPayPwdDTO) {
        String bizUserId = String.valueOf(AuthUserContext.get().getUserId());
        // 查询用户信息，补充用户姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        updatePhoneByPayPwdDTO.setName(userInfo.getName());
        updatePhoneByPayPwdDTO.setIdentityNo(userInfo.getIdentityCardNo());
        updatePhoneByPayPwdDTO.setOldPhone(userInfo.getPhone());
        String backUrl = domainUrl + AllinpayNoticeUrl.UPDATE_PHONE_BY_PAY_PWD;
        // 返回通联页面url
        String url = allinpayService.updatePhoneByPayPwd(bizUserId, backUrl, updatePhoneByPayPwdDTO);
        return ServerResponseEntity.success(url);
    }

    @GetMapping("/queryBindAcct")
    @Operation(summary = "查询已绑定的支付账户用户标识", description = "查询已绑定的支付账户用户标识")
    public ServerResponseEntity<QueryBindAcctResp> queryBindAcct() {
        String bizUserId = String.valueOf(AuthUserContext.get().getUserId());
        QueryBindAcctResp resp = allinpayService.queryBindAcct(bizUserId);
        return ServerResponseEntity.success(resp);
    }

    @PostMapping("/signAcctProtocol")
    @Operation(summary = "账户提现协议签约", description = "账户提现协议签约")
    public ServerResponseEntity<String> signAcctProtocol(@RequestBody SignAcctProtocolDTO signAcctProtocolDTO) {
        Long userId = AuthUserContext.get().getUserId();
        // 查询用户信息，补充用户姓名
        UserInfo userInfo = allinpayService.getUserInfo(userId.toString());
        signAcctProtocolDTO.setSignAcctName(userInfo.getName());
        String backUrl = domainUrl + AllinpayNoticeUrl.SIGN_ACCT_PROTOCOL;
        // 请求签约，返回签约地址
        String url = allinpayService.signAcctProtocol(String.valueOf(userId), backUrl, signAcctProtocolDTO);
        return ServerResponseEntity.success(url);
    }

    @GetMapping("/signContractQuery")
    @Operation(summary = "账户协议签约查询", description = "账户协议签约查询")
    public ServerResponseEntity<String> signContractQuery(SignAcctProtocolDTO signAcctProtocolDTO) {
        Long userId = AuthUserContext.get().getUserId();
        String url = allinpayService.signContractQuery(String.valueOf(userId), signAcctProtocolDTO);
        return ServerResponseEntity.success(url);
    }

    @PostMapping("/applyBindBankCard")
    @Operation(summary = "请求绑定银行卡", description = "请求绑定银行卡")
    public ServerResponseEntity<ApplyBindBankCardResp> applyBindBankCard(@RequestBody ApplyBankCardDTO applyBankCardDTO) {
        String bizUserId = AuthUserContext.get().getUserId().toString();
        // 查询通联用户信息，补充姓名和身份证号
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        applyBankCardDTO.setName(userInfo.getName());
        applyBankCardDTO.setIdentityNo(userInfo.getIdentityCardNo());
        // 请求绑定银行卡
        ApplyBindBankCardResp resp = allinpayService.applyBindBankCard(bizUserId, applyBankCardDTO);
        return ServerResponseEntity.success(resp);
    }

    @PutMapping("/bindBankCard")
    @Operation(summary = "绑定银行卡", description = "绑定银行卡")
    public ServerResponseEntity<Void> bindBankCard(@RequestBody BindBankCardDTO bindBankCardDTO) {
        Long userId = AuthUserContext.get().getUserId();
        allinpayService.bindBankCard(String.valueOf(userId), bindBankCardDTO);
        return ServerResponseEntity.success();
    }

    @PutMapping("/unbindBankCard")
    @Operation(summary = "解绑银行卡", description = "解绑银行卡")
    public ServerResponseEntity<Void> unbindBankCard(@RequestBody UnbindBankCardDTO unbindBankCardDTO) {
        Long userId = AuthUserContext.get().getUserId();
        allinpayService.unbindBankCard(String.valueOf(userId), unbindBankCardDTO);
        return ServerResponseEntity.success();
    }

    @GetMapping("/queryBankCard")
    @Operation(summary = "查询银行卡", description = "查询银行卡")
    @Parameter(name = "cardNo", description = "银行卡号(不传则查询全部银行卡)")
    public ServerResponseEntity<List<BindCard>> queryBankCard(@RequestParam(value = "cardNo", required = false) String cardNo) {
        Long userId = AuthUserContext.get().getUserId();
        List<BindCard> bindCards = allinpayService.queryBankCard(String.valueOf(userId), cardNo);
        return ServerResponseEntity.success(bindCards);
    }

    @PostMapping("/sendVerificationCode")
    @Operation(summary = "发送短信验证码", description = "发送短信验证码")
    public ServerResponseEntity<Void> sendVerificationCode(@RequestBody VerificationCodeDTO verificationCodeDTO) {
        String bizUserId = AuthUserContext.get().getUserId().toString();
        allinpayService.sendVerificationCode(bizUserId, verificationCodeDTO);
        return ServerResponseEntity.success();
    }

    @PostMapping("/bindPhone")
    @Operation(summary = "绑定手机", description = "绑定手机")
    public ServerResponseEntity<Void> bindPhone(@RequestBody VerificationCodeDTO verificationCodeDTO) {
        String bizUserId = AuthUserContext.get().getUserId().toString();
        // 判断当前用户是否绑定了无感注册的默认手机号，是则先进行解绑
        UserInfo userInfo = allinpayService.getUserInfo(bizUserId);
        if (userInfo.getIsPhoneChecked()
                && Objects.equals(userInfo.getPhone(), AllinpayConstant.DEFAULT_BIND_PHONE_NUMBER)) {
            VerificationCodeDTO unbindDTO = new VerificationCodeDTO();
            unbindDTO.setPhone(AllinpayConstant.DEFAULT_BIND_PHONE_NUMBER);
            allinpayService.unbindPhone(bizUserId, unbindDTO);
        }
        allinpayService.bindPhone(bizUserId, verificationCodeDTO);
        // 并更新用户拓展信息
        UserExtensionDTO userExtensionDTO = new UserExtensionDTO();
        userExtensionDTO.setUserId(AuthUserContext.get().getUserId());
        userExtensionDTO.setAllinpayPhoneBind(1);
        userExtensionFeignClient.updateExtension(userExtensionDTO);
        return ServerResponseEntity.success();
    }

    @PutMapping("/unbindPhone")
    @Operation(summary = "解绑手机", description = "解绑手机")
    public ServerResponseEntity<Void> unbindPhone(@RequestBody VerificationCodeDTO verificationCodeDTO) {
        Long userId = AuthUserContext.get().getUserId();
        allinpayService.unbindPhone(String.valueOf(userId), verificationCodeDTO);
        return ServerResponseEntity.success();
    }

    @PutMapping("/changeBindPhone")
    @Operation(summary = "修改绑定手机(银行卡验证版)", description = "修改绑定手机(银行卡验证版)")
    public ServerResponseEntity<BankCardChangeBindPhoneResp> changeBindPhone(@RequestBody BankCardChangeBindPhoneDTO bankCardChangeBindPhoneDTO) {
        String bizUserId = String.valueOf(AuthUserContext.get().getUserId());
        BankCardChangeBindPhoneResp resp = allinpayService.bankCardChangeBindPhone(bizUserId, bankCardChangeBindPhoneDTO);
        return ServerResponseEntity.success(resp);
    }

    @PutMapping("/confirmChangeBindPhone")
    @Operation(summary = "确认修改绑定手机(银行卡验证版)", description = "确认修改绑定手机(银行卡验证版)")
    public ServerResponseEntity<Void> confirmChangeBindPhone(@RequestBody VerifyBankCardChangeBindPhoneDTO verifyBankCardChangeBindPhoneDTO) {
        String bizUserId = String.valueOf(AuthUserContext.get().getUserId());
        allinpayService.verifyBankCardChangeBindPhone(bizUserId, verifyBankCardChangeBindPhoneDTO);
        return ServerResponseEntity.success();
    }

    @PostMapping("/createMember")
    @Operation(summary = "创建会员", description = "创建会员")
    public ServerResponseEntity<Void> createMember() {
        UidInfoBO uidInfoBO = AuthUserContext.get();
        allinpayService.createMember(uidInfoBO.getUserId().toString(), uidInfoBO.getSysType());
        // 更新用户拓展信息为已创建
        UserExtensionDTO userExtensionDTO = new UserExtensionDTO();
        userExtensionDTO.setUserId(uidInfoBO.getUserId());
        userExtensionDTO.setAllinpayCreate(1);
        userExtensionFeignClient.updateExtension(userExtensionDTO);
        return ServerResponseEntity.success();
    }

    @GetMapping("/getBankcardBin")
    @Operation(summary = "查询卡bin", description = "查询卡bin")
    @Parameter(name = "cardNo", description = "卡号")
    public ServerResponseEntity<CardBinInfo> getBankcardBin(String cardNo) {
        CardBinInfo cardBinInfo = allinpayService.getBankCardBin(cardNo);
        return ServerResponseEntity.success(cardBinInfo);
    }
}
