package com.propertyManagement.business.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.propertyManagement.business.domain.WxFamilyMember;
import com.propertyManagement.business.domain.WxProprietorLedger;
import com.propertyManagement.business.domain.WxUser;
import com.propertyManagement.business.domain.WxUserCommunityLedger;
import com.propertyManagement.business.domain.bo.CodeLoginBo;
import com.propertyManagement.business.domain.vo.LoginWxUser;
import com.propertyManagement.business.domain.vo.WxCommunityVo;
import com.propertyManagement.business.mapper.WxFamilyMemberMapper;
import com.propertyManagement.business.mapper.WxProprietorLedgerMapper;
import com.propertyManagement.business.mapper.WxUserCommunityLedgerMapper;
import com.propertyManagement.business.mapper.WxUserMapper;
import com.propertyManagement.common.core.domain.LoginResult;
import com.propertyManagement.common.enums.UserPermission;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 商户登录校验方法
 *
 * @author liushuai
 * @date 2025/05/13
 */
@Slf4j
@Component
public class WxUserLoginService {
    @Autowired
    private WxUserTokenService wxUserTokenService;

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private WxProprietorLedgerMapper proprietorLedgerMapper;

    @Autowired
    private WxUserCommunityLedgerMapper wxUserCommunityLedgerMapper;

    @Autowired
    private WxFamilyMemberMapper familyMemberMapper;

    @Autowired
    private IWxCommunityService wxCommunityService;

    @Autowired
    private WxMaService wxMaDormService;

    /**
     * 微信小程序授权登录
     *
     * @param bo 登录参数
     * @return LoginResult
     */
    public LoginResult codeLogin(CodeLoginBo bo) {
        try {
            WxMaJscode2SessionResult session = wxMaDormService.getUserService().getSessionInfo(bo.getPayCode());
            String openId = session.getOpenid();
            String unionId = session.getUnionid();

            LambdaQueryWrapper<WxUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WxUser::getOpenId,openId);
            WxUser wxUser = wxUserMapper.selectOne(queryWrapper);

            LoginWxUser loginWxUser = new LoginWxUser();
            if (null != wxUser) {
                BeanUtils.copyProperties(wxUser, loginWxUser);
                // 生成token
                String token = wxUserTokenService.createToken(loginWxUser);
                return getLoginResult(loginWxUser, token, null , null);
            } else {
                // TODO 生成新用户
                WxUser newUser = new WxUser();
                newUser.setOpenId(openId);
                newUser.setUnionId(unionId);
                if (wxUserMapper.insert(newUser) > 0) {
                    BeanUtils.copyProperties(newUser,loginWxUser);
                    // 生成token
                    String token = wxUserTokenService.createToken(loginWxUser);
                    return getLoginResult(loginWxUser, token, null , null);
                }
            }
        } catch (WxErrorException e) {
            log.warn("微信授权登录失败！", e);
            return LoginResult.loginErr("微信授权登录失败");
        }
        return LoginResult.loginErr("微信授权登录失败");
    }

    /**
     * 微信小程序授权手机号登录
     *
     * @param bo 登录参数
     * @return 登录结果
     */
    public LoginResult codeMobilLogin(CodeLoginBo bo) {
        try {
            WxMaJscode2SessionResult session = wxMaDormService.getUserService().getSessionInfo(bo.getPayCode());
            WxMaPhoneNumberInfo phoneNoInfo = wxMaDormService.getUserService().getPhoneNoInfo(bo.getLoginCode());
            String openId = session.getOpenid();
            String phoneNumber = phoneNoInfo.getPhoneNumber();
//            String phoneNumber = "13937112070";
            LambdaQueryWrapper<WxUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WxUser::getMobile,phoneNumber);
            WxUser user = wxUserMapper.selectOne(queryWrapper);

            LoginWxUser loginMemberUser = new LoginWxUser();
            if (null != user) {
                BeanUtils.copyProperties(user, loginMemberUser);
                // 生成token
                String token = wxUserTokenService.createToken(loginMemberUser);
                return getLoginResult(loginMemberUser, token, bo.getLatitude(), bo.getLongitude());
            } else {
                // TODO 生成新用户
                WxUser newUser = new WxUser();
                /**
                 * 根据手机号查询是否有匹配台账数据,不为空则是业主，为空则是访客
                 */
                LambdaQueryWrapper<WxProprietorLedger> proprietorLedgerQueryWrapper = Wrappers.lambdaQuery();
                proprietorLedgerQueryWrapper.apply("FIND_IN_SET({0}, phone)", phoneNumber);
                List<WxProprietorLedger> ledgerList = proprietorLedgerMapper.selectList(proprietorLedgerQueryWrapper);
                /**
                 * 当前手机号是否为家庭成员
                 */
                LambdaQueryWrapper<WxFamilyMember> familyMemberLambdaQueryWrapper = Wrappers.lambdaQuery();
                familyMemberLambdaQueryWrapper.eq(WxFamilyMember::getPhone, phoneNumber);
                List<WxFamilyMember> familyMemberList = familyMemberMapper.selectList(familyMemberLambdaQueryWrapper);
                if (!ledgerList.isEmpty()) {
                    newUser.setUserPermission(UserPermission.ONE.getCode());
                }else if (!familyMemberList.isEmpty()) {
                    newUser.setUserPermission(UserPermission.TWO.getCode());
                }else {
                    newUser.setUserPermission(UserPermission.THREE.getCode());
                }
                newUser.setOpenId(openId);
                newUser.setMobile(phoneNumber);
                if (StringUtils.isNotBlank(bo.getEncryptedData()) && StringUtils.isNotBlank(bo.getIv())) {
                    WxMaUserInfo userInfo = wxMaDormService.getUserService().getUserInfo(session.getSessionKey(), bo.getEncryptedData(), bo.getIv());
                    newUser.setNickName(userInfo.getNickName() + "_" + phoneNumber);
                    newUser.setAvatar(userInfo.getAvatarUrl());
                }else {
                    newUser.setNickName(phoneNumber);
                    newUser.setAvatar("https://llwy-1356792742.cos.ap-beijing.myqcloud.com/%E5%88%A9%E9%BE%99%E7%89%A9%E4%B8%9A%20logo.png");
                }
                if (bo.getLongitude() > 0 && bo.getLatitude() > 0) {
                    newUser.setLongitude(bo.getLongitude());
                    newUser.setLatitude(bo.getLatitude());
                }
                if (wxUserMapper.insert(newUser) > 0) {
                    /**
                     * 台账信息存在则绑定关联关系
                     */
                    if (!ledgerList.isEmpty()) {
                        wxUserCommunityLedgerMapper.insertBatch(ledgerList.stream().map(item -> {
                            WxUserCommunityLedger ledger = new WxUserCommunityLedger();
                            ledger.setUserId(newUser.getId());
                            ledger.setCommunityId(item.getCommunityId());
                            ledger.setProprietorId(item.getProprietorId());
                            return ledger;
                        }).collect(Collectors.toList()));
                    }
                    /**
                     * 家庭成员绑定户主指定的小区与户号
                     */
                    if (!familyMemberList.isEmpty()) {
                        WxFamilyMember familyMember = familyMemberList.get(0);
                        WxUserCommunityLedger ledger = new WxUserCommunityLedger();
                        ledger.setUserId(newUser.getId());
                        ledger.setCommunityId(familyMember.getCommunityId());
                        ledger.setProprietorId(familyMember.getProprietorId());
                        wxUserCommunityLedgerMapper.insert(ledger);
                    }
                    BeanUtils.copyProperties(newUser,loginMemberUser);
                    String token = wxUserTokenService.createToken(loginMemberUser);
                    return getLoginResult(loginMemberUser, token, bo.getLatitude(), bo.getLongitude());
                }
            }
        }
        catch (Exception e) {
            log.warn("微信授权登录失败！", e);
            return LoginResult.loginErr("微信授权登录失败");
        }
        return LoginResult.loginErr("微信授权登录失败");
    }


    /**
     * 登录验证
     *
     * @param username 用户名
     * @param password 密码
     * @return 结果
     */
    public LoginResult<WxUser> login(String username, String password) {
        LambdaQueryWrapper<WxUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WxUser::getMobile,username);
        WxUser user = wxUserMapper.selectOne(queryWrapper);

        LoginWxUser loginMemberUser = new LoginWxUser();
        BeanUtils.copyProperties(user, loginMemberUser);
        // 生成token
        String token = wxUserTokenService.createToken(loginMemberUser);
        return getLoginResult(loginMemberUser, token, null, null);
    }

    private LoginResult getLoginResult(LoginWxUser wxUser, String token, Double latitude, Double longitude) {
        LoginResult loginResult = new LoginResult();
        loginResult.setToken(token);
        loginResult.setLoginFlag(true);
        /**
         * 如果经纬度不为空，则根据当前用户位置匹配最近小区
         */
        if (latitude > 0 && longitude > 0) {
            WxCommunityVo communityVo = wxCommunityService.queryByTargetLatAndTargetLon(latitude, longitude);
            if (null != communityVo) {
                wxUser.setCommunityId(communityVo.getCommunityId());
                wxUser.setCommunityName(communityVo.getCommunityName());
            }
        }
        loginResult.setUser(wxUser);
        return loginResult;
    }
}
