package com.microservices.zone.member.service;

import com.microservices.zone.member.domain.points.ZonePointsAccount;
import com.microservices.zone.member.domain.vo.*;
import com.microservices.zone.resource.domain.ZoneResource;

import java.util.List;

/**
 * 专区积分账户Service接口
 *
 * @author otto
 */
public interface IZonePointsAccountService {
    /**
     * 查询专区积分账户
     *
     * @param id 专区积分账户主键
     * @return 专区积分账户
     */
    public ZonePointsAccount selectZonePointsAccountById(Long id);

    /**
     * 查询专区积分账户列表
     *
     * @param zonePointsAccount 专区积分账户
     * @return 专区积分账户集合
     */
    public List<ZonePointsAccount> selectZonePointsAccountList(ZonePointsAccount zonePointsAccount);

    /**
     * 新增专区积分账户
     *
     * @param inputVo 专区积分账户
     * @return 结果
     */
    public int insertZonePointsAccount(ZonePointsAccountInputVo inputVo);

    /**
     * 修改专区积分账户
     *
     * @param updateVo 专区积分账户
     * @return 结果
     */
    public int updateZonePointsAccount(ZonePointsAccountUpdateVo updateVo);

    /**
     * 批量删除专区积分账户
     *
     * @param ids 需要删除的专区积分账户主键
     * @return 结果
     */
    public int deleteZonePointsAccountByIds(Long[] ids);

    /**
     * 删除专区积分账户信息
     *
     * @param id 专区积分账户主键
     * @return 结果
     */
    public int deleteZonePointsAccountById(Long id);

    /**
     * 根据用户ID和专区ID查询积分账户
     *
     * @param userId 用户ID
     * @param zoneId 专区ID
     * @return 专区积分账户
     */
    ZonePointsAccount selectZonePointsAccountByUserIdAndZoneId(Long userId, Long zoneId);

    /**
     * 获取当前登录用户的积分账户总览信息
     *
     * @param zoneId 专区ID
     * @return 积分账户总览（包含累计获取积分、累计消费积分）
     */
    ZonePointsOverviewVo getCurrentUserPointsOverview(Long zoneId);

    /**
     * 获取当前登录用户的置顶文章信息
     *
     * @param zoneId 专区ID
     * @return 置顶文章信息（无置顶文章时返回null）
     */
    ZonePointsTopDocVo getCurrentUserPointsTopDoc(Long zoneId);

    /**
     * 查询专区下置顶文章列表（过期时间晚于当前时间，用于前台展示）
     *
     * @param zoneId 专区ID
     * @return 置顶文章列表
     */
    List<ZonePointsTopDocVo> selectTopDocList(Long zoneId);

    /**
     * 获取当前登录用户的置顶项目信息
     *
     * @param zoneId 专区ID
     * @return 置顶项目信息（无置顶项目时返回null）
     */
    ZonePointsTopProjectVo getZonePointsTopProject(Long zoneId);

    /**
     * 根据会员ID查询积分账户列表
     *
     * @param memberId 专区会员ID
     * @return 专区积分账户列表
     */
    List<ZonePointsAccount> selectZonePointsAccountByMemberId(Long memberId);

    /**
     * 异步创建会员积分账户并记录流水（不阻塞主业务）
     *
     * @param userId    用户ID
     * @param zoneId    专区ID
     * @param operatorId 操作人ID（当前登录用户ID，无则默认0）
     * @param deptId    deptID
     */
    void createPointsAccountAsync(Long userId, Long zoneId, Long operatorId, Long deptId);

    /**
     * 增加每日首次访问积分（异步方式）
     *
     * @param zoneId 专区ID
     * @return 是否新增成功（false表示今日已领取）
     */
    void addDailyVisitPointsAsync(Long zoneId);

    /**
     * 从 Redis 队列中消费积分异步任务（在主线程执行，事务正常生效）
     *
     * @return 处理的任务数量
     */
    int processPointsAsyncQueue();

    /**
     * 增加资源发布积分（异步方式，写入 Redis 队列）
     *
     * @param zoneResource 专区资源
     */
    void addPublishResourcePointsAsync(ZoneResource zoneResource);

    /**
     * 增加项目关联积分（异步方式，写入 Redis 队列）
     *
     * @param userId 用户ID
     * @param zoneId 专区ID
     * @param sourceId 来源ID（项目ID）
     * @param projectName 项目名称
     * @param operatorId 操作人ID
     */
    void addRelevanceProjectPointsAsync(Long userId, Long zoneId, Long sourceId, String projectName, Long operatorId);

    /**
     * 电子证书积分扣减
     *
     * @param inputVo 积分事件输入对象
     * @return true=扣减成功，false=扣减失败（积分不足）
     */
    boolean deductPointsForCertificate(ZonePointsTransactionInputVo inputVo);

    /**
     * 文章置顶积分扣减
     *
     * @param zoneId 专区ID
     * @param id     文章ID
     * @param name   文章名称
     * @return true=扣减成功，false=扣减失败（积分不足）
     */
    boolean deductPointsForArticleTop(Long zoneId, Long id, String name);

    /**
     * 项目置顶积分扣减
     *
     * @param zoneId 专区ID
     * @param id     项目ID
     * @param name   项目名称
     * @return true=扣减成功，false=扣减失败（积分不足）
     */
    boolean deductPointsForProjectTop(Long zoneId, Long id, String name);

    /**
     * 线下活动积分冻结（前台用户操作，业务层已做会员身份+积分专区+幂等+积分校验）
     *
     * @param inputVo 积分申请输入对象
     */
    void freezePointsForOfflineActivity(ZonePointsApplyInputVo inputVo);

    /**
     * 专家答疑积分冻结（前台用户操作，业务层已做会员身份+积分专区+幂等+积分校验）
     *
     * @param inputVo 积分申请输入对象
     */
    void freezePointsForExpertQa(ZonePointsApplyInputVo inputVo);

    /**
     * 驳回积分申请（管理员操作）
     * 查询对应申请记录（pending状态），更新状态为fail，
     * 同时更新pointsEvent的subject括号内容为"已退回"、replyContent为驳回原因，
     * 并触发积分解冻操作
     *
     * @param inputVo 积分申请输入对象（id、reply必填）
     */
    void rejectPointsApply(ZonePointsApplyInputVo inputVo);

    /**
     * 通过积分申请（管理员操作）
     * 查询对应申请记录（pending状态），更新状态为success，
     * 同时更新pointsEvent的subject去除原括号内容，
     * 并从冻结积分中正式扣减积分（含总积分扣减）
     *
     * @param inputVo 积分申请输入对象（id、reply必填）
     */
    void approvePointsApply(ZonePointsApplyInputVo inputVo);

    /**
     * 增加资源下载积分（异步方式，写入 Redis 队列）
     *
     * @param fileId     文件ID
     * @param sourceData 来源描述（如下载者信息）
     */
    void addDownloadResourcePointsAsync(Long fileId, String sourceData);

    /**
     * 将失败任务落库保存
     *
     * @param taskData  任务JSON数据
     * @param lastError 失败原因
     */
    void saveFailLog(String taskData, String lastError);
}