package com.njzscloud.dispose.sys.auth.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.security.module.password.PasswordLoginForm;
import com.njzscloud.common.security.module.wechat.mini.WechatMiniLoginForm;
import com.njzscloud.common.security.support.IAuthService;
import com.njzscloud.common.security.support.UserDetail;
import com.njzscloud.dispose.finance.mapper.MoneyAccountMapper;
import com.njzscloud.dispose.finance.pojo.entity.MoneyAccountEntity;
import com.njzscloud.dispose.sys.auth.mapper.AuthMapper;
import com.njzscloud.dispose.sys.auth.pojo.result.EndpointResource;
import com.njzscloud.dispose.sys.auth.pojo.result.IdentityInfo;
import com.njzscloud.dispose.sys.auth.pojo.result.MenuResource;
import com.njzscloud.dispose.sys.auth.pojo.result.MyResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Set;

import static com.njzscloud.common.security.contant.Constants.ROLE_ANONYMOUS;
import static com.njzscloud.common.security.contant.Constants.ROLE_AUTHENTICATED;

/**
 * 登录
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthService implements IAuthService {
    private final AuthMapper authMapper;
    private final MoneyAccountMapper moneyAccountMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDetail selectUser(PasswordLoginForm form) {
        MyResult myResult = authMapper.selectUser(Wrappers.query().eq("a.username", form.getAccount()).eq("a.deleted", 0));
        return my(myResult, form.getClientCode().getVal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDetail selectUser(WechatMiniLoginForm form) {
        String openid = form.getOpenid();
        String unionid = form.getUnionid();
        MyResult myResult = authMapper.selectUser(Wrappers.query().eq("a.wechat_openid", openid)
            .eq(StrUtil.isNotBlank(unionid), "a.wechat_unionid", unionid)
            .eq("a.deleted", 0));
        return my(myResult, form.getClientCode().getVal());
    }

    @Override
    public Set<String> selectRole(Long userId) {
        Set<String> roles = authMapper.selectRole(userId);
        roles.add(ROLE_AUTHENTICATED);
        roles.add(ROLE_ANONYMOUS);
        return roles;
    }

    /**
     * 获取当前登录人信息
     */
    @Override
    public UserDetail my(Long userId, Integer client) {
        UserDetail userDetail = authMapper.selectUser(Wrappers.query().eq("b.id", userId).eq("a.deleted", 0));
        Assert.notNull(userDetail, () -> Exceptions.exception("未查询到用户信息"));
        return my(userDetail, client);
    }

    public UserDetail my(UserDetail userDetail, Integer client) {
        if (userDetail == null) return null;
        Long userId = userDetail.getUserId();
        Assert.notNull(userDetail, () -> Exceptions.exception("未查询到用户信息"));
        List<MenuResource> menuResources = authMapper.selectUserMenu(userId, client);
        List<EndpointResource> endpointResources = authMapper.selectUserEndpoint(userId);
        List<IdentityInfo> identityInfoList = authMapper.selectUserIdentity(userId);
        Long currentCustomerId = null;
        MoneyAccountEntity moneyAccount = moneyAccountMapper.selectOne(Wrappers.<MoneyAccountEntity>lambdaQuery()
            .eq(MoneyAccountEntity::getUserId, userId)
            .eq(MoneyAccountEntity::getDeleted, Boolean.FALSE));

        if (CollUtil.isNotEmpty(identityInfoList)) {
            IdentityInfo identityInfo = identityInfoList.getFirst();
            currentCustomerId = identityInfo.getCustomerId();
        }
        Set<String> roles = authMapper.selectRole(userId);
        roles.add(ROLE_AUTHENTICATED);
        roles.add(ROLE_ANONYMOUS);
        return BeanUtil.copyProperties(userDetail, MyResult.class)
            .setRecharge(moneyAccount == null ? BigDecimal.ZERO : moneyAccount.getRecharge())
            .setRevenue(moneyAccount == null ? BigDecimal.ZERO : moneyAccount.getRevenue())
            .setCurrentCustomerId(currentCustomerId)
            .setIdentities(identityInfoList)
            .setMenus(menuResources)
            .setEndpoints(endpointResources)
            .setRoles(roles)
            .setClient(client)
            ;
    }

}
