package com.jeesharp.business.modules.member.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeesharp.business.modules.member.constants.MobileAuthConstants;
import com.jeesharp.business.modules.member.entity.Member;
import com.jeesharp.business.modules.member.entity.MemberOauth;
import com.jeesharp.business.modules.member.mapper.MemberMapper;
import com.jeesharp.business.modules.member.enums.OauthAppTypeEnum;
import com.jeesharp.business.modules.member.enums.OauthPlatformEnum;
import com.jeesharp.business.modules.member.mapper.MemberOauthMapper;
import com.jeesharp.business.modules.member.service.MemberOauthService;
import com.jeesharp.business.modules.member.vo.MemberOauthQueryVO;
import com.jeesharp.framework.mybatis.core.service.CrudService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 会员第三方 OAuth 绑定
 *
 * @author jeesharp
 * @version 2026-03-19
 */
@Slf4j
@Service
@Transactional(readOnly = true)
public class MemberOauthServiceImpl extends CrudService<MemberOauthMapper, MemberOauth, MemberOauthQueryVO>
        implements MemberOauthService {

    @Autowired
    private MemberMapper memberMapper;

    @Override
    public MemberOauth getByPlatformAppTypeAppIdOpenid(String platform, String appType, String appId, String openid) {
        if (StrUtil.hasBlank(platform, appType, openid)) {
            return null;
        }
        String appIdNorm = StrUtil.blankToDefault(appId, "");
        LambdaQueryWrapper<MemberOauth> w = new LambdaQueryWrapper<>();
        w.eq(MemberOauth::getPlatform, platform)
                .eq(MemberOauth::getAppType, appType)
                .eq(MemberOauth::getAppId, appIdNorm)
                .eq(MemberOauth::getOpenid, openid);
        return this.getOne(w);
    }

    @Override
    public MemberOauth getFirstByPlatformAndUnionid(String platform, String unionid) {
        if (StrUtil.hasBlank(platform, unionid)) {
            return null;
        }
        LambdaQueryWrapper<MemberOauth> w = new LambdaQueryWrapper<>();
        w.eq(MemberOauth::getPlatform, platform)
                .eq(MemberOauth::getUnionid, unionid)
                .orderByDesc(MemberOauth::getCreateDate)
                .last("LIMIT 1");
        return this.getOne(w);
    }

    @Override
    public Member resolveMemberForWechatMini(String oauthAppIdKey, String openId, String unionId) {
        String appIdNorm = StrUtil.blankToDefault(oauthAppIdKey, "");
        MemberOauth oauth = getByPlatformAppTypeAppIdOpenid(
                OauthPlatformEnum.WECHAT.getValue(),
                OauthAppTypeEnum.MINI.getValue(),
                appIdNorm,
                openId);
        if (oauth != null) {
            return memberMapper.selectById(oauth.getMemberId());
        }
        if (StrUtil.isNotBlank(unionId)) {
            oauth = getFirstByPlatformAndUnionid(OauthPlatformEnum.WECHAT.getValue(), unionId);
            if (oauth != null) {
                return memberMapper.selectById(oauth.getMemberId());
            }
        }
        return null;
    }

    @Override
    public Member resolveMemberForJustAuthSource(String justAuthSource, String unionId, String openId, String oauthAppId) {
        String[] platformAppType = platformAndAppTypeForJustAuth(justAuthSource);
        if (platformAppType == null) {
            return null;
        }
        String platform = platformAppType[0];
        String appType = platformAppType[1];
        String appIdNorm = StrUtil.blankToDefault(oauthAppId, "");
        if (StrUtil.isNotBlank(unionId)) {
            MemberOauth oauth = getFirstByPlatformAndUnionid(platform, unionId);
            if (oauth != null && StrUtil.isNotBlank(oauth.getMemberId())) {
                return memberMapper.selectById(oauth.getMemberId());
            }
        }
        if (StrUtil.isNotBlank(openId) && StrUtil.isNotBlank(appType)) {
            MemberOauth oauth = null;
            if (StrUtil.isNotBlank(appIdNorm)) {
                oauth = getByPlatformAppTypeAppIdOpenid(platform, appType, appIdNorm, openId);
            }
            if (oauth == null) {
                oauth = getByPlatformAppTypeAppIdOpenid(platform, appType, "", openId);
            }
            if (oauth != null && StrUtil.isNotBlank(oauth.getMemberId())) {
                return memberMapper.selectById(oauth.getMemberId());
            }
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void upsertJustAuthBinding(String memberId, String justAuthSource, String unionId, String openId, String oauthAppId) {
        if (StrUtil.isBlank(memberId) || StrUtil.isBlank(openId)) {
            return;
        }
        String[] platformAppType = platformAndAppTypeForJustAuth(justAuthSource);
        if (platformAppType == null) {
            return;
        }
        String platform = platformAppType[0];
        String appType = platformAppType[1];
        String appIdNorm = StrUtil.blankToDefault(oauthAppId, "");
        MemberOauth row = getByPlatformAppTypeAppIdOpenid(platform, appType, appIdNorm, openId);
        if (row == null && StrUtil.isNotBlank(appIdNorm)) {
            row = getByPlatformAppTypeAppIdOpenid(platform, appType, "", openId);
        }
        if (row != null) {
            if (!memberId.equals(row.getMemberId())) {
                log.warn("OAuth 绑定冲突：openId 已绑定其他会员，source={} openId={} existingMemberId={} ignoreMemberId={}",
                        justAuthSource, openId, row.getMemberId(), memberId);
                return;
            }
            boolean needUpdate = false;
            if (StrUtil.isNotBlank(unionId) && !unionId.equals(StrUtil.blankToDefault(row.getUnionid(), ""))) {
                row.setUnionid(unionId);
                needUpdate = true;
            }
            if (StrUtil.isNotBlank(appIdNorm) && !appIdNorm.equals(StrUtil.blankToDefault(row.getAppId(), ""))) {
                row.setAppId(appIdNorm);
                needUpdate = true;
            }
            if (needUpdate) {
                row.preUpdate();
                super.save(row);
            }
            return;
        }
        MemberOauth m = new MemberOauth();
        m.setMemberId(memberId);
        m.setPlatform(platform);
        m.setAppType(appType);
        m.setAppId(appIdNorm);
        m.setOpenid(openId);
        m.setUnionid(unionId);
        m.preInsert();
        super.save(m);
    }

    /**
     * @return [platform, appType]，无法映射时返回 null
     */
    private String[] platformAndAppTypeForJustAuth(String justAuthSource) {
        if (StrUtil.isBlank(justAuthSource)) {
            return null;
        }
        switch (justAuthSource) {
            case MobileAuthConstants.JUSTAUTH_WECHAT_MP:
                return new String[] { OauthPlatformEnum.WECHAT.getValue(), OauthAppTypeEnum.MP.getValue() };
            case MobileAuthConstants.JUSTAUTH_WECHAT_APP:
                return new String[] { OauthPlatformEnum.WECHAT.getValue(), OauthAppTypeEnum.APP.getValue() };
            case MobileAuthConstants.JUSTAUTH_QQ:
                return new String[] { OauthPlatformEnum.QQ.getValue(), OauthAppTypeEnum.OPEN.getValue() };
            case MobileAuthConstants.JUSTAUTH_ALIPAY:
                return new String[] { OauthPlatformEnum.ALIPAY.getValue(), OauthAppTypeEnum.OPEN.getValue() };
            case MobileAuthConstants.JUSTAUTH_WEIBO:
                return new String[] { OauthPlatformEnum.WEIBO.getValue(), OauthAppTypeEnum.OPEN.getValue() };
            case MobileAuthConstants.JUSTAUTH_DOUYIN:
                return new String[] { OauthPlatformEnum.DOUYIN.getValue(), OauthAppTypeEnum.OPEN.getValue() };
            case MobileAuthConstants.JUSTAUTH_HUAWEI_APP:
                return new String[] { OauthPlatformEnum.HUAWEI.getValue(), OauthAppTypeEnum.APP.getValue() };
            case MobileAuthConstants.JUSTAUTH_HUAWEI_ATOMIC:
                return new String[] { OauthPlatformEnum.HUAWEI.getValue(), OauthAppTypeEnum.ATOMIC.getValue() };
            case MobileAuthConstants.JUSTAUTH_HUAWEI:
                return new String[] { OauthPlatformEnum.HUAWEI.getValue(), OauthAppTypeEnum.OPEN.getValue() };
            default:
                return null;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void upsertWechatMiniBinding(String memberId, String appId, String openid, String unionid) {
        if (StrUtil.hasBlank(memberId, openid)) {
            return;
        }
        String appIdNorm = StrUtil.blankToDefault(appId, "");
        String platform = OauthPlatformEnum.WECHAT.getValue();
        String appType = OauthAppTypeEnum.MINI.getValue();

        MemberOauth row = getByPlatformAppTypeAppIdOpenid(platform, appType, appIdNorm, openid);
        if (row != null) {
            if (!memberId.equals(row.getMemberId())) {
                log.warn("OAuth 绑定冲突：openid 已绑定其他会员，openId={} existingMemberId={} ignoreMemberId={}",
                        openid, row.getMemberId(), memberId);
                return;
            }
            boolean needUpdate = false;
            if (StrUtil.isNotBlank(unionid) && !unionid.equals(StrUtil.blankToDefault(row.getUnionid(), ""))) {
                row.setUnionid(unionid);
                needUpdate = true;
            }
            if (StrUtil.isNotBlank(appIdNorm) && !appIdNorm.equals(StrUtil.blankToDefault(row.getAppId(), ""))) {
                row.setAppId(appIdNorm);
                needUpdate = true;
            }
            if (needUpdate) {
                row.preUpdate();
                super.save(row);
            }
            return;
        }

        MemberOauth m = new MemberOauth();
        m.setMemberId(memberId);
        m.setPlatform(platform);
        m.setAppType(appType);
        m.setAppId(appIdNorm);
        m.setOpenid(openid);
        m.setUnionid(unionid);
        m.preInsert();
        super.save(m);
    }

    @Override
    public String getWechatMiniOpenidByMemberIdAppId(String memberId, String appId) {
        if (StrUtil.isBlank(memberId)) {
            return "";
        }
        String appIdNorm = StrUtil.blankToDefault(appId, "");
        String platform = OauthPlatformEnum.WECHAT.getValue();
        String appType = OauthAppTypeEnum.MINI.getValue();

        LambdaQueryWrapper<MemberOauth> w = new LambdaQueryWrapper<>();
        w.eq(MemberOauth::getMemberId, memberId)
            .eq(MemberOauth::getPlatform, platform)
            .eq(MemberOauth::getAppType, appType)
            .eq(MemberOauth::getAppId, appIdNorm)
            .orderByDesc(MemberOauth::getCreateDate)
            .last("LIMIT 1");
        MemberOauth row = this.getOne(w);
        if (row != null && StrUtil.isNotBlank(row.getOpenid())) {
            return row.getOpenid();
        }

        if (StrUtil.isNotBlank(appIdNorm)) {
            LambdaQueryWrapper<MemberOauth> fallback = new LambdaQueryWrapper<>();
            fallback.eq(MemberOauth::getMemberId, memberId)
                .eq(MemberOauth::getPlatform, platform)
                .eq(MemberOauth::getAppType, appType)
                .eq(MemberOauth::getAppId, "")
                .orderByDesc(MemberOauth::getCreateDate)
                .last("LIMIT 1");
            row = this.getOne(fallback);
            if (row != null && StrUtil.isNotBlank(row.getOpenid())) {
                return row.getOpenid();
            }
        }
        return "";
    }
}
