package org.dromara.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.config.BoManConfig;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.domain.houseInfo.HouseInfo;
import org.dromara.domain.residentInfo.ResidentInfo;
import org.dromara.domain.residentInfo.bo.ResidentInfoBo;
import org.dromara.domain.residentInfo.vo.ResidentInfoVo;
import org.dromara.mapper.HouseInfoMapper;
import org.dromara.mapper.ResidentInfoMapper;
import org.dromara.service.IResidentInfoService;
import org.dromara.system.domain.SysRole;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.SysUserRole;
import org.dromara.system.domain.SysUserTenant;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysRoleVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SysRoleMapper;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.mapper.SysUserRoleMapper;
import org.dromara.system.mapper.SysUserTenantMapper;
import org.dromara.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import static org.dromara.common.core.constant.Constants.*;

/**
 * 居住人员信息，存储居住人员的详细信息Service业务层处理
 *
 * @author boman
 * @date 2025-04-11
 */
@RequiredArgsConstructor
@Service
public class ResidentInfoServiceImpl implements IResidentInfoService {

    private final ResidentInfoMapper baseMapper;
    private final SysUserTenantMapper sysUserTenantMapper;
    private final SysUserMapper sysUserMapper;
    private final ISysUserService userService;
    private final SysRoleMapper sysRoleMapper;
    private final SysUserRoleMapper userRoleMapper;
    private final HouseInfoMapper houseInfoMapper;


    /**
     * 查询居住人员信息，存储居住人员的详细信息
     *
     * @param residentId 主键
     * @return 居住人员信息，存储居住人员的详细信息
     */
    @Override
    public ResidentInfoVo queryById(Long residentId) {
        return baseMapper.selectVoById(residentId);
    }

    /**
     * 获取居住人员信息 过滤租户
     *
     * @param residentId 主键
     */
    @Override
    public ResidentInfoVo getAuthenticationInfo(Long residentId) {
        return TenantHelper.ignore(() -> {
            return
                baseMapper.selectVoById(residentId);
        });
    }

    /**
     * 根据userId获取居住人员信息
     *
     * @param userId
     * @return
     */
    @Override
    public ResidentInfoVo getInfoByUserId(Long userId) {
        return baseMapper.getInfoByUserId(userId);
    }

    /**
     * 分页查询居住人员信息，存储居住人员的详细信息列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 居住人员信息，存储居住人员的详细信息分页列表
     */
    @Override
    public TableDataInfo<ResidentInfoVo> queryPageList(ResidentInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ResidentInfo> lqw = buildQueryWrapper(bo);
        Page<ResidentInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询居住人员需要认证的列表
     */
    @Override
    public TableDataInfo<ResidentInfoVo> listAuthentication(ResidentInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ResidentInfo> lqw = buildQueryWrapper(bo);
        Page<ResidentInfoVo> result = TenantHelper.ignore(() -> {
            return
                baseMapper.selectVoPage(pageQuery.build(), lqw);
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的居住人员信息，存储居住人员的详细信息列表
     *
     * @param bo 查询条件
     * @return 居住人员信息，存储居住人员的详细信息列表
     */
    @Override
    public List<ResidentInfoVo> queryList(ResidentInfoBo bo) {
        LambdaQueryWrapper<ResidentInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ResidentInfo> buildQueryWrapper(ResidentInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ResidentInfo> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(ResidentInfo::getResidentId);
        lqw.eq(bo.getHouseId() != null, ResidentInfo::getHouseId, bo.getHouseId());
        lqw.eq(bo.getUserId() != null, ResidentInfo::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getDetailedAddress()), ResidentInfo::getDetailedAddress, bo.getDetailedAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getResidentType()), ResidentInfo::getResidentType, bo.getResidentType());
        lqw.like(StringUtils.isNotBlank(bo.getResidentName()), ResidentInfo::getResidentName, bo.getResidentName());
        lqw.eq(StringUtils.isNotBlank(bo.getResidentIdCard()), ResidentInfo::getResidentIdCard, bo.getResidentIdCard());
        lqw.eq(StringUtils.isNotBlank(bo.getResidentBirthday()), ResidentInfo::getResidentBirthday, bo.getResidentBirthday());
        lqw.eq(StringUtils.isNotBlank(bo.getResidentPhone()), ResidentInfo::getResidentPhone, bo.getResidentPhone());
        lqw.eq(bo.getResidentGender() != null, ResidentInfo::getResidentGender, bo.getResidentGender());
        lqw.eq(StringUtils.isNotBlank(bo.getResidentRelationship()), ResidentInfo::getResidentRelationship, bo.getResidentRelationship());
        lqw.eq(StringUtils.isNotBlank(bo.getIsHouseholder()), ResidentInfo::getIsHouseholder, bo.getIsHouseholder());
        lqw.eq(StringUtils.isNotBlank(bo.getIsTenant()), ResidentInfo::getIsTenant, bo.getIsTenant());
        lqw.eq(StringUtils.isNotBlank(bo.getResidentEmployer()), ResidentInfo::getResidentEmployer, bo.getResidentEmployer());
        lqw.eq(StringUtils.isNotBlank(bo.getSpecialType()), ResidentInfo::getSpecialType, bo.getSpecialType());
        lqw.eq(StringUtils.isNotBlank(bo.getResidentHobby()), ResidentInfo::getResidentHobby, bo.getResidentHobby());
        lqw.eq(StringUtils.isNotBlank(bo.getResidentAppearance()), ResidentInfo::getResidentAppearance, bo.getResidentAppearance());
        lqw.eq(StringUtils.isNotBlank(bo.getIdCardFront()), ResidentInfo::getIdCardFront, bo.getIdCardFront());
        lqw.eq(StringUtils.isNotBlank(bo.getIdCardBack()), ResidentInfo::getIdCardBack, bo.getIdCardBack());
        lqw.eq(StringUtils.isNotBlank(bo.getIdCardAddress()), ResidentInfo::getIdCardAddress, bo.getIdCardAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getFacePhoto()), ResidentInfo::getFacePhoto, bo.getFacePhoto());
        lqw.eq(StringUtils.isNotBlank(bo.getExamine()), ResidentInfo::getExamine, bo.getExamine());
        return lqw;
    }

    /**
     * 新增居住人员提交认证信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(ResidentInfoBo bo) {
        ResidentInfo add = MapstructUtils.convert(bo, ResidentInfo.class);
        //根据租户id houseId 手机号查询该居住人员是否存在
        if (checkIdCardUnique(add)) {
            throw new UserException("resident.register.save.error", add.getResidentName());
        }
        String tenantId = bo.getTenantId();
        Long userId = LoginHelper.getUserId();
        add.setUserId(userId);
        String residentType = add.getResidentType();
        String isHouseholder = add.getIsHouseholder();
        //必须是业主和户主才能去修改房本信息
        if (ONE.equals(residentType) && Y.equals(isHouseholder)) {
            List<HouseInfo> houseInfoList = bo.getHouseInfoList();
            if (houseInfoList != null && !houseInfoList.isEmpty()) {
                //修改房屋信息
                return TenantHelper.ignore(() -> {
                    return houseInfoMapper.updateBatchById(houseInfoList);
                });
            }
        }
        if (THR.equals(residentType)){
            SysUserBo user = new SysUserBo();
            user.setUserId(userId);
            user.setTenantId(tenantId);
            user.setResidentType(residentType);
            //默认审核通过
            add.setExamine(TWO);
            //赋予角色
            //sys_user_tenant表中
            SysUserTenant sysUserTenant = new SysUserTenant();
            sysUserTenant.setUserId(userId);
            sysUserTenant.setTenantId(tenantId);
            sysUserTenantMapper.insert(sysUserTenant);
            //给该userId赋予角色
            // 新增用户与角色管理
            //根据权限字符去查询角色id
            SysRoleVo sysRoleVo = TenantHelper.ignore(() -> {
                return sysRoleMapper.selectVoOne(new LambdaQueryWrapper<SysRole>()
                    //TENEMENT住户固定角色名称
                    .eq(SysRole::getRoleKey, VISITOR)
                    .eq(SysRole::getTenantId, add.getTenantId()));
            });
            if (sysRoleVo != null) {
                Long[] longArray = new Long[1];
                longArray[0] = sysRoleVo.getRoleId();
                user.setRoleIds(longArray);
            }
            userService.insertUserRole(user, false);

            if (TenantHelper.isEnable()) {
                //把租户id更新到sys_user表/sys_user_tenant表中
                user.setIsAuthentication(Y);
                userService.updateUserByIdNoTenantId(user);
            }
        }

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setResidentId(add.getResidentId());
        }
        return flag;
    }

    /**
     * 管理员新增居住人员信息，默认就审核过
     *
     * @param bo 居住人员信息，存储居住人员的详细信息
     * @return 是否新增成功
     */
    @Override
    public Boolean addResidentInfo(ResidentInfoBo bo) {
        ResidentInfo add = MapstructUtils.convert(bo, ResidentInfo.class);
        String tenantId = add.getTenantId();
        String residentPhone = add.getResidentPhone();
        //validEntityBeforeSave(add);
        //校验该租户下居住人员是否存在
        //根据租户id houseId 手机号查询该居住人员是否存在
        if (checkIdCardUnique(add)) {
            throw new UserException("resident.register.save.error", add.getResidentName());
        }

        //校验账号是否存在,如果存在则不新增账号
        //校验该租户下居住人员是否存在
        boolean existUser = TenantHelper.ignore(() -> {
            return sysUserMapper.exists(new LambdaQueryWrapper<SysUser>().eq(SysUser::getTenantId, tenantId)
                .eq(SysUser::getPhonenumber, add.getResidentPhone()));
        });
        //新增账号信息
        Long userId;
        SysUserBo user = new SysUserBo();
        user.setTenantId(tenantId);
        if (!existUser) {
            user.setUserName(residentPhone);
            user.setPhonenumber(residentPhone);
            user.setUserName(residentPhone);
            user.setNickName(residentPhone);
            user.setPassword(BCrypt.hashpw(BoManConfig.getPasswordDeft()));
            // 校验用户类型是否存在
            String userType = UserType.getUserType(add.getUserType()).getUserType();
            user.setUserType(userType);
            user.setIsAuthentication(Y);
            user.setCreateBy(0L);
            user.setUpdateBy(0L);
            SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
            TenantHelper.ignore(() -> {
                sysUserMapper.insert(sysUser);
            });
            userId = sysUser.getUserId();
        } else {
            //从sysUser表中查询
            SysUserVo sysUserVo = TenantHelper.ignore(() -> {
                return sysUserMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, residentPhone));
            });
            userId = sysUserVo.getUserId();
            user.setUserId(userId);
        }
        add.setExamine(TWO);
        add.setUserId(userId);
        boolean flag = baseMapper.insert(add) > 0;
        //sys_user_tenant表中
        SysUserTenant sysUserTenant = new SysUserTenant();
        sysUserTenant.setUserId(userId);
        sysUserTenant.setTenantId(tenantId);
        sysUserTenantMapper.insert(sysUserTenant);
        //给该userId赋予角色
        // 新增用户与角色管理
        //根据权限字符去查询角色id
        SysRoleVo sysRoleVo = TenantHelper.ignore(() -> {
            return sysRoleMapper.selectVoOne(new LambdaQueryWrapper<SysRole>()
                //TENEMENT住户固定角色名称
                .eq(SysRole::getRoleKey, TENEMENT)
                .eq(SysRole::getTenantId, add.getTenantId()));
        });
        if (sysRoleVo != null) {
            Long[] longArray = new Long[1];
            longArray[0] = sysRoleVo.getRoleId();
            user.setRoleIds(longArray);
        }
        userService.insertUserRole(user, false);
        if (flag) {
            bo.setResidentId(add.getResidentId());
        }
        return flag;
    }

    /**
     * 修改居住人员信息，存储居住人员的详细信息
     *
     * @param bo 居住人员信息，存储居住人员的详细信息
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(ResidentInfoBo bo) {
        ResidentInfo update = MapstructUtils.convert(bo, ResidentInfo.class);
        validEntityBeforeSave(update);
/*        //根据租户id houseId 手机号查询该居住人员是否存在
        if (checkIdCardUnique(update)) {
            throw new UserException("resident.register.save.error", update.getResidentName());
        }*/
        String residentType = update.getResidentType();
        String isHouseholder = update.getIsHouseholder();
        //必须是业主和户主才能去修改房本信息
        if (ONE.equals(residentType) && Y.equals(isHouseholder)) {
            List<HouseInfo> houseInfoList = bo.getHouseInfoList();
            if (houseInfoList != null && !houseInfoList.isEmpty()) {
                //修改房屋信息
                 TenantHelper.ignore(() -> {
                    return houseInfoMapper.updateBatchById(houseInfoList);
                });
            }
        }
        if (bo.getIsFilter()) {
            return TenantHelper.ignore(() -> {
                return baseMapper.updateById(update) > 0;
            });
        } else {
            return baseMapper.updateById(update) > 0;
        }
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ResidentInfo entity) {

    }

    /**
     * 校验身份证号码是否唯一
     *
     * @param entity 住户信息
     * @return 结果
     */

    public boolean checkIdCardUnique(ResidentInfo entity) {
        boolean exit = TenantHelper.ignore(() -> {
            return
                baseMapper.exists(new LambdaQueryWrapper<ResidentInfo>()
                    .eq(entity.getHouseId() != null, ResidentInfo::getHouseId, entity.getHouseId())
                    .eq(entity.getTenantId() != null, ResidentInfo::getTenantId, entity.getTenantId())
                    .eq(StringUtils.isNotBlank(entity.getResidentPhone()), ResidentInfo::getResidentPhone, entity.getResidentPhone())
                );
        });
        return exit;
    }

    /**
     * 校验并批量删除居住人员信息，存储居住人员的详细信息信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 查询居住人员党员数量
     */
    @Override
    public R<Long> selectCount(ResidentInfoBo residentInfo) {
        ResidentInfo update = MapstructUtils.convert(residentInfo, ResidentInfo.class);
        return R.ok(baseMapper.selectCount(new LambdaQueryWrapper<ResidentInfo>().eq(ResidentInfo::getResidentAppearance, update.getResidentAppearance())));
    }

    /**
     * 居住用户认证审核
     *
     * @param bo 员工信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean examineResident(ResidentInfoBo bo) {
        ResidentInfo residentInfo = MapstructUtils.convert(bo, ResidentInfo.class);
        String tenantId = residentInfo.getTenantId();
        if (TWO.equals(residentInfo.getExamine())) {
            SysUserBo sysUser = new SysUserBo();
            sysUser.setUserId(bo.getUserId());
            if (TenantHelper.isEnable()) {
                //把租户id更新到sys_user表/sys_user_tenant表中
                sysUser.setTenantId(tenantId);
                sysUser.setIsAuthentication(Y);
                userService.updateUserByIdNoTenantId(sysUser);
                SysUserTenant sysUserTenant = new SysUserTenant();
                sysUserTenant.setUserId(residentInfo.getUserId());
                sysUserTenant.setTenantId(tenantId);
                sysUserTenantMapper.insert(sysUserTenant);
            }
            //给该userId赋予角色
            // 新增用户与角色管理
            //根据权限字符去查询角色id
            SysRoleVo sysRoleVo = TenantHelper.ignore(() -> {
                return sysRoleMapper.selectVoOne(new LambdaQueryWrapper<SysRole>()
                    //TENEMENT住户固定角色名称
                    .eq(SysRole::getRoleKey, TENEMENT)
                    .eq(SysRole::getTenantId, tenantId));
            });
            if (sysRoleVo != null) {
                Long[] longArray = new Long[1];
                longArray[0] = sysRoleVo.getRoleId();
                sysUser.setRoleIds(longArray);
            }
            userService.insertUserRole(sysUser, false);
        }
        return baseMapper.updateById(residentInfo) > 0;
    }


    /**
     * 删除居住人员的认证信息
     *
     * @param bo 主键串
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteResident(ResidentInfoBo bo) {
        Long userId = bo.getUserId();
        Long residentId = bo.getResidentId();
        String tenantId = bo.getTenantId();
        boolean flag = baseMapper.deleteById(residentId) > 0;
        // userMapper.deleteById(userId);
        if (TenantHelper.isEnable()) {
            List<ResidentInfo> residentInfoList = TenantHelper.ignore(() -> {
                return baseMapper.selectList(new LambdaQueryWrapper<ResidentInfo>().eq(ResidentInfo::getUserId, userId));
            });
            //查询该用户是否一个认证信息 通过的 都没有则需要把用户租户重置为000000，认证状态改为未认证
            SysUser sysUser = new SysUser();
            sysUser.setUserId(userId);
            if (residentInfoList == null) {
                sysUser.setTenantId(TENANT_ID);
                sysUser.setIsAuthentication(N);
                TenantHelper.ignore(() -> {
                    sysUserMapper.updateById(sysUser);
                });
            }
            // 删除用户与角色关联
            TenantHelper.ignore(() -> {
                userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId).eq(SysUserRole::getTenantId, tenantId));
            });
            // 删除用户与租户关联
            TenantHelper.ignore(() -> {
                sysUserTenantMapper.delete(new LambdaQueryWrapper<SysUserTenant>().eq(SysUserTenant::getUserId, userId).eq(SysUserTenant::getTenantId, tenantId));
            });
            if (residentInfoList != null && !residentInfoList.isEmpty()) {
                //判断用户的默认租户是否是被删除的那个租户，是的情况下换一个租户id给sysUser表中
                SysUserVo sysUserVo = TenantHelper.ignore(() -> {
                    return sysUserMapper.selectVoById(userId);
                });
                String tenantIdOld = sysUserVo.getTenantId();
                if (tenantId.equals(tenantIdOld)) {
                    SysUserTenant sysUserTenant = sysUserTenantMapper.selectVoOne(new LambdaQueryWrapper<SysUserTenant>().eq(SysUserTenant::getUserId, userId));
                    sysUser.setTenantId(TENANT_ID);
                    if (sysUserTenant != null) {
                        sysUser.setTenantId(sysUserTenant.getTenantId());
                    }

                }

                long count = residentInfoList.stream().filter(e -> e.getExamine().equals(TWO)).count();
                if (count == 0) {
                    sysUser.setTenantId(TENANT_ID);
                    sysUser.setIsAuthentication(N);
                    TenantHelper.ignore(() -> {
                        sysUserMapper.updateById(sysUser);
                    });
                }
            }
        } else {
            userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        }
        return flag;
    }

    /**
     * 管理员修改住户管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editAuthentication(ResidentInfoBo bo) {
        ResidentInfo residentInfo = MapstructUtils.convert(bo, ResidentInfo.class);
        //判断是否修改了租户
        ResidentInfoVo residentInfoVo = baseMapper.selectVoById(residentInfo.getResidentId());
        String tenantIdOld = residentInfoVo.getTenantId();
        String tenantIdNew = residentInfo.getTenantId();
        Long userId = residentInfoVo.getUserId();
        SysUserBo sysUser = new SysUserBo();
        sysUser.setUserId(bo.getUserId());
        sysUser.setTenantId(tenantIdNew);
        if (!tenantIdOld.equals(tenantIdNew)) {
            sysUserTenantMapper.update(new LambdaUpdateWrapper<SysUserTenant>()
                .set(SysUserTenant::getTenantId, tenantIdNew)
                .eq(SysUserTenant::getUserId, userId).eq(SysUserTenant::getTenantId, tenantIdOld));

            //组装sysUser
            //给该userId赋予角色
            // 新增用户与角色管理
            //根据权限字符去查询角色id
            SysRoleVo sysRoleVo = TenantHelper.ignore(() -> {
                return sysRoleMapper.selectVoOne(new LambdaQueryWrapper<SysRole>()
                    //TENEMENT住户固定角色名称
                    .eq(SysRole::getRoleKey, TENEMENT)
                    .eq(SysRole::getTenantId, tenantIdNew));
            });
            if (sysRoleVo != null) {
                Long[] longArray = new Long[1];
                longArray[0] = sysRoleVo.getRoleId();
                sysUser.setRoleIds(longArray);
            }
            userService.insertUserRole(sysUser, true);
        }
        sysUser.setPhonenumber(residentInfo.getResidentPhone());
        userService.updateUserByIdNoTenantId(sysUser);
        return baseMapper.updateById(residentInfo) > 0;
    }
}
