package com.apobates.forum.member.api.service;

import java.time.LocalDateTime;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Stream;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.event.elderly.MemberActionDescriptor;
import com.apobates.forum.member.MemberProfileBean;
import com.apobates.forum.member.entity.*;
import com.apobates.forum.member.exception.MemberNamesExistException;
import com.apobates.forum.member.exception.MemberNamesProtectException;

/**
 * 会员的业务层接品
 * 
 * @author xiaofanku
 * @since 20190304
 */
public interface MemberService {
	/**
	 * 根据会员的登录帐号搜索会员
	 * 
	 * @param suggestNameWord 会员的登录帐号
	 * @param pageSize        显示的数量
	 * @return
	 */
	Stream<Member> searchByNames(String suggestNameWord, int pageSize);
	
	/**
	 * 根据会员的登录帐号搜索会员
	 * 
	 * @param suggestNameWord 会员的登录帐号
	 * @return
	 */
	Stream<Member> searchByNames(String suggestNameWord);
	
	/**
	 * 查看指定集合的会员信息
	 * 
	 * @param idList 会员ID列表
	 * @return
	 */
	Stream<Member> queryCollection(List<Long> idList);
	
	/**
	 * 最近注册的会员
	 * 
	 * @param size 显示的数量
	 * @return
	 */
	Stream<Member> getRecent(int size);
	
	/**
	 * 更新会员的登录密码
	 * 
	 * @param id               会员ID
	 * @param oldUnEncryptPswd 现在的密码
	 * @param newUnEncryptPswd 更新后的密码
	 * @param actionDescriptor 会员请求描述符
	 * @return
	 */
	Optional<Boolean> editPswd(long id, String oldUnEncryptPswd, String newUnEncryptPswd, MemberActionDescriptor actionDescriptor)throws IllegalStateException;

	/**
	 * 更新会员的登录密码 找回密码的第二步
	 * 
	 * @param id               会员ID
	 * @param newUnEncryptPswd 新的密码
	 * @param actionDescriptor 会员请求描述符
	 * @return
	 */
	Optional<Boolean> resetPswd(long id, String newUnEncryptPswd, MemberActionDescriptor actionDescriptor);
	
	/**
	 * 更新会员的个性签名和昵称
	 * 
	 * @param id               会员ID
	 * @param signature        个性签名
	 * @param nickname         网名/昵称
	 * @param actionDescriptor 会员的操作统计
	 * @return
	 */
	Optional<Boolean> edit(long id, String signature, String nickname, MemberActionDescriptor actionDescriptor);

	/**
	 * 更新会员头像
	 * 
	 * @param id                    会员ID
	 * @param encodeAvtarFormatPath 编码后的头像路径
	 * @param actionDescriptor      会员操作描述符
	 * @return
	 */
	Optional<Boolean> updateAvatar(long id, String encodeAvtarFormatPath, MemberActionDescriptor actionDescriptor);
	
	/**
	 * 检查会员登录帐号的唯一性.如果是帐号保护也返回失败
	 * 
	 * @param memberNames 会员登录帐号
	 * @return 
	 */
	Optional<Boolean> checkNamesUnique(String memberNames)throws MemberNamesProtectException, MemberNamesExistException;
	
	/**
	 * 创建新的会员/注册会员, 操作成功后会发送通知(MemberSignUpEvent)
	 * 
	 * @param memberNames      会员登录帐号
	 * @param unEncryptPswd    未加密的密码
	 * @param inviteCode       邀请码
	 * @param nickname         昵称
	 * @param actionDescriptor 会员请求描述符
	 * @return 
	 */
	Optional<Member> signUp(String memberNames, String unEncryptPswd, String inviteCode, String nickname, MemberActionDescriptor actionDescriptor)throws IllegalStateException;
	
	/**
	 * 创建社区经理
	 * 
	 * @param memberNames      登录帐号
	 * @param unEncryptPswd    未加密的密码
	 * @param nickname         会员昵称
	 * @param role             角色
	 * @param actionDescriptor 会员操作描述符
	 * @return 
	 */
	long create(String memberNames, String unEncryptPswd, String nickname, MemberRoleEnum role, MemberActionDescriptor actionDescriptor)throws IllegalStateException;
	
	/**
	 * 查看指定的会员, 操作成功后会发送通知(MemberSignInEvent)
	 * 
	 * @param memberNames      会员登录帐号
	 * @param unEncryptPswd    未加密的密码
	 * @param actionDescriptor 会员请求描述符
	 * @return
	 */
	Optional<Member> signIn(String memberNames, String unEncryptPswd, MemberActionDescriptor actionDescriptor)throws IllegalStateException;

	/**
	 * 查看指定的会员
	 * 
	 * @param memberNames      会员登录帐号
	 * @param unEncryptPswd    未加密的密码
	 * @param isAdmin          是否是管理员身份
	 * @param actionDescriptor 会员请求描述符
	 * @return
	 */
	Optional<Member> signIn(String memberNames, String unEncryptPswd, boolean isAdmin, MemberActionDescriptor actionDescriptor)throws IllegalStateException;
	
	/**
	 * 会员注销登录
	 * 
	 * @param memberNames      会员登录帐号
	 * @param member           会员
	 * @param actionDescriptor 会员请求描述符
	 */
	Optional<Boolean> signOut(String memberNames, Member member, MemberActionDescriptor actionDescriptor);

	/**
	 * 将会员的默认组(CARD)提升至VIP
	 * @deprecated
	 * @param memberId 会员ID
	 * @param duration 有效日期时长
	 * @param unit 有效日期单位,只接受ForumCalendarUnitEnum.MONTH(月),只接受ForumCalendarUnitEnum.YEAR(年)
	 * @throws IllegalStateException
	 * @throws IllegalArgumentException
	 * @return
	 */
	Optional<Boolean> exchangeVIP(long memberId, int duration, ForumCalendarUnitEnum unit)throws IllegalStateException, IllegalArgumentException;

	/**
	 * 将会员的默认组(CARD)提升至VIP
	 *
	 * @param memberId 会员ID
	 * @param duration 有效日期时长
	 * @param unit 有效日期单位,只接受ForumCalendarUnitEnum.MONTH(月),只接受ForumCalendarUnitEnum.YEAR(年)
	 * @param transerial 交易流水号
	 * @return
	 * @throws IllegalStateException
	 * @throws IllegalArgumentException
	 */
	Optional<Boolean> exchangeVIP(long memberId, int duration, ForumCalendarUnitEnum unit, String transerial)throws IllegalStateException, IllegalArgumentException;

	/**
	 * 查看指定的会员
	 * 
	 * @param id 会员ID
	 * @return
	 */
	Optional<Member> get(long id);
	
	/**
	 * 会员的登录帐号是否存在
	 * 
	 * @param memberNames 会员登录帐号
	 * @return 成功返回会员登录密码绑定的盐
	 */
	Optional<String> getMemberSalt(String memberNames);
	
	/**
	 * 查看会员的头像
	 * 
	 * @param id 会员ID
	 * @return
	 */
	Optional<String> getMemberAvatar(long id);
	
	/**
	 * 会员的登录帐号是否存在
	 * 
	 * @param memberNames 会员登录帐号
	 * @return 成功返回会员ID,不存在返回-1
	 */
	long existMemberNames(String memberNames);
	
	/**
	 * 会员合计
	 * 
	 * @return
	 */
	long count();
	
	/**
	 * 计算会员的个人汇总信息
	 * 
	 * @param id          会员ID
	 * @param actionStats 会员的操作统计
	 * @return
	 */
	Optional<MemberProfileBean> getMemberProfileBean(long id, EnumMap<ForumActionEnum, Long> actionStats);
	
	/**
	 * 计算会员的个人汇总信息
	 * 
	 * @param idList      会员ID列表
	 * @param actionStats 会员的操作统计,Key=会员ID, Value=Map.key=操作枚举, Map.value=操作的统计数
	 * @return
	 */
	List<MemberProfileBean> getMemberProfileBeanes(List<Long> idList, Map<Long, EnumMap<ForumActionEnum, Long>> actionStats);
	
	/**
	 * 统计指定日期范围内会员注册的数量
	 * 
	 * @param start  开始日期
	 * @param finish 结束日期
	 * @return Key = YYYY-MM-DD, Value=注册数
	 */
	TreeMap<String, Long> groupMemberForBirthDate(LocalDateTime start, LocalDateTime finish);
	
	/**
	 * 分组统计不同状态的会员数量
	 * 
	 * @return Key=Member.status, Value=会员数量
	 */
	EnumMap<MemberStatusEnum, Long> groupMemberForStatus();
	
	/**
	 * 分组统计不同角色的会员数量
	 * 
	 * @return Key=Member.mrole, Value=会员数量
	 */
	EnumMap<MemberRoleEnum, Long> groupMemberForRole();
	
	/**
	 * 分组统计不同组的会员数量
	 * 
	 * @return Key=Member.mgroup, Value=会员数量
	 */
	EnumMap<MemberGroupEnum, Long> groupMemberForGroup();
	
	/**
	 * 查看指定的邀请码是否可用
	 * 
	 * @param inviteCode 邀请码
	 * @return 返回的key：code(参数),id(可用时大于0,反之0)
	 */
	Map<String, String> getActiveInviteCode(String inviteCode);
}
