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

import com.jeesharp.business.modules.member.dto.MemberSaveDTO;
import com.jeesharp.business.modules.member.dto.MemberThirdPartyLoginOutcome;
import com.jeesharp.business.modules.member.entity.Member;
import com.jeesharp.business.modules.member.vo.MemberDisplayVO;
import com.jeesharp.business.modules.member.vo.MemberImportVO;
import com.jeesharp.business.modules.member.vo.MemberOrderDisplay;
import com.jeesharp.business.modules.member.vo.MemberQueryVO;
import com.jeesharp.framework.mybatis.core.service.BaseInterface;
import com.jeesharp.framework.pojo.vo.ImportRespVO;

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

/**
 * 会员服务接口
 *
 * @author jeesharp
 * @version 2024-01-24
 */
public interface MemberService extends BaseInterface<Member, MemberQueryVO> {

    /**
     * 按主键批量查询会员（未删除）。
     *
     * @param ids 会员主键集合
     * @return 会员列表
     */
    List<Member> listByIds(List<String> ids);

    /**
     * 按关键词模糊匹配会员主键（编号/昵称/姓名/手机/主键）。
     *
     * @param keyword 关键词
     * @return 匹配的会员 ID 列表，无匹配时返回空列表
     */
    List<String> findIdsByKeyword(String keyword);

    /**
     * 按关键词匹配会员主键，不限当前登录租户（发券等运营场景）。
     *
     * @param keyword 关键词（会员编号、手机号等）
     * @return 匹配的会员 ID 列表，无匹配时返回空列表
     */
    List<String> findIdsByKeywordForGrant(String keyword);

    /**
     * 批量获取会员管理端展示摘要，key 为会员主键。
     *
     * @param memberIds 会员主键集合
     * @return 会员主键 → 展示摘要
     */
    Map<String, MemberDisplayVO> mapDisplayByIds(List<String> memberIds);

    /**
     * 为业务行批量写入会员编号、展示姓名、手机号码。
     *
     * @param rows 实现 {@link MemberOrderDisplay} 的行集合
     */
    <T extends MemberOrderDisplay> void enrichMemberDisplay(List<T> rows);

    /**
     * 为单行写入会员编号、展示姓名、手机号码。
     *
     * @param row 实现 {@link MemberOrderDisplay} 的业务行
     */
    void enrichMemberDisplay(MemberOrderDisplay row);

    /**
     * 批量删除会员
     *
     * @param ids ID集合
     */
    void deleteData(List<String> ids);

    /**
     * 导入会员数据
     *
     * @param list 导入数据列表
     * @return ImportRespVO 导入结果
     */
    ImportRespVO importData(List<MemberImportVO> list);

    /**
     * 根据手机号查询会员
     *
     * @param mobile 手机号
     * @return 会员信息
     */
    Member getByMobile(String mobile);

    /**
     * 根据邮箱查询会员
     *
     * @param email 邮箱
     * @return 会员信息
     */
    Member getByEmail(String email);

    /**
     * 根据会员编号查询会员
     *
     * @param memberNo 会员编号
     * @return 会员信息
     */
    Member getByMemberNo(String memberNo);

    /**
     * 校验手机号是否唯一
     *
     * @param mobile    手机号
     * @param excludeId 排除的ID（更新时使用）
     * @return true-唯一 false-已存在
     */
    boolean checkMobileUnique(String mobile, String excludeId);

    /**
     * 生成会员编号
     *
     * @return 会员编号
     */
    String generateMemberNo();

    /**
     * 确保会员已分配编号；若为空则生成并持久化。
     *
     * @param memberId 会员主键
     * @return 会员编号
     */
    String ensureMemberNo(String memberId);

    /**
     * 增加积分
     *
     * @param memberId 会员ID
     * @param points   积分数量
     * @param bizType  业务类型
     * @param bizId    业务ID
     * @param bizDesc  业务描述
     */
    void addPoints(String memberId, Integer points, String bizType, String bizId, String bizDesc);

    /**
     * 增加积分并关联规则，返回流水 ID。
     */
    String addPointsWithRule(String memberId, Integer points, String bizType, String bizId, String bizDesc,
                             String ruleId, String ruleName, java.time.LocalDateTime expireDate, String operateSource);

    /**
     * 扣减积分
     *
     * @param memberId 会员ID
     * @param points   积分数量
     * @param bizType  业务类型
     * @param bizId    业务ID
     * @param bizDesc  业务描述
     */
    void deductPoints(String memberId, Integer points, String bizType, String bizId, String bizDesc);

    /**
     * 扣减积分并关联规则，返回流水 ID。
     */
    String deductPointsWithRule(String memberId, Integer points, String bizType, String bizId, String bizDesc,
                                String ruleId, String ruleName, String operateSource);

    /**
     * 增加成长值
     *
     * @param memberId    会员ID
     * @param growthValue 成长值
     * @param bizType     业务类型
     * @param bizDesc     业务描述
     */
    void addGrowthValue(String memberId, Integer growthValue, String bizType, String bizDesc);

    /**
     * 更新会员等级
     *
     * @param memberId 会员ID
     */
    void updateMemberLevel(String memberId);

    List<String> getMemberFeatureCodes(String memberId);

    /**
     *
     * @param id
     * @param status
     */
    void updateStatus(String id, Integer status);

    void saveData(MemberSaveDTO dto);

    /**
     * 认证场景：通过手机号创建会员（走 {@link #saveData(MemberSaveDTO)}）。
     *
     * @param mobile     手机号
     * @param inviteCode 邀请码，可空
     * @param source     会员来源，可空时默认 APP
     * @return 创建后的会员
     */
    Member createMemberByMobileForAuth(String mobile, String inviteCode, String source);

    /**
     * 认证场景：仅邮箱创建会员。
     *
     * @param email      邮箱
     * @param inviteCode 邀请码，可空
     * @param source     会员来源
     * @return 持久化后的会员
     */
    Member createMemberByEmailForAuth(String email, String inviteCode, String source);

    /**
     * 认证场景：按账号解析会员（当前支持手机号）。
     *
     * @param account 登录账号
     * @return 会员或 null
     */
    Member findMemberByAccountForAuth(String account);

    /**
     * JustAuth 第三方登录：按平台源查找会员，不存在则创建并写入第三方标识字段。
     *
     * @param source     与 MobileAuthConstants 中 JUSTAUTH_* 一致
     * @param inviteCode 邀请码，可空（预留）
     * @param unionId    平台 unionId
     * @param openId     平台 openId
     * @param nickname   昵称
     * @param avatar     头像
     * @param oauthAppId 写入 app_member_oauth.app_id：X-App-Id 或与当前 JustAuth 渠道一致的 client-id，可空
     * @return 会员及是否本次新建
     */
    MemberThirdPartyLoginOutcome findOrCreateMemberForThirdParty(
            String source,
            String inviteCode,
            String unionId,
            String openId,
            String nickname,
            String avatar,
            String oauthAppId);

    /**
     * 记录会员登录成功：更新最后登录时间、IP、方式，并累加登录次数。
     *
     * @param memberId  会员主键
     * @param loginType 登录方式（如 APP、WECHAT_MINI），可空时保留原值
     */
    void recordLoginSuccess(String memberId, String loginType);
}
