using System;
using BaseGames.Core.Events;
using QuestStateEnum = BaseGames.Core.Events.QuestState;
namespace BaseGames.Quest
{
// =========================================================================
// QuestLockReason / QuestLockInfo ── 任务锁定原因(强类型 API)
// =========================================================================
/// 任务无法接取的原因枚举。 表示无锁定(可接取)。
public enum QuestLockReason
{
/// 无锁定,任务当前可以接取。
None,
/// 任务已在进行中(Active)。
AlreadyActive,
/// 任务已完成(Completed)。
AlreadyCompleted,
/// 任务已失败(Failed)。
Failed,
/// 任务已暂停(Paused)。
Paused,
/// 任务 ID 未找到或资产未加载。
NotFound,
/// 好感度或存档数据尚未初始化。
DataNotLoaded,
/// NPC 好感度不足。 格式:"{actual}/{min}"。
InsufficientAffinity,
/// 前置任务未完成。 为该前置任务的 questId。
RequiresQuest,
/// 世界状态标志条件未满足。
FlagConditionNotMet,
}
///
/// 任务锁定信息(强类型版本)。
/// 相比字符串 Key,可在编译期检查原因类型,UI 层无需手动解析冒号分隔的参数。
/// 通过 可转换为与旧版 GetQuestLockReason 兼容的 Key 格式。
///
public struct QuestLockInfo
{
/// 锁定原因枚举值。 表示无锁定(可接取)。
public QuestLockReason Reason;
///
/// 附带参数(可选):
/// - :前置任务 questId
/// - :格式 "{actual}/{min}"
///
public string Param;
/// 任务当前是否处于锁定状态(不可接取)。
public bool IsLocked => Reason != QuestLockReason.None;
///
/// 转换为本地化 Key 格式,与旧版 完全兼容。
/// 格式:"Quest.LockReason.{Reason}";有参数时为 "Quest.LockReason.{Reason}:{Param}"。
///
public string ToLocalizationKey() =>
Reason == QuestLockReason.None
? string.Empty
: string.IsNullOrEmpty(Param)
? $"Quest.LockReason.{Reason}"
: $"Quest.LockReason.{Reason}:{Param}";
}
///
/// 任务管理器的公开契约。ServiceLocator.Get<IQuestManager>() 获取实例,
/// 避免外部代码直接依赖 QuestManager 具体类型。
///
public interface IQuestManager
{
/// 接取任务(幂等)。
void AcceptQuest(string questId);
///
/// 主动放弃进行中的任务(Active → Available/Unavailable),清除目标进度。
/// 非 Active 状态的任务调用此方法无效。
///
void AbandonQuest(string questId);
/// 完成任务并发放奖励。rewardTarget 接收奖励(如玩家)。
void CompleteQuest(string questId, IRewardTarget rewardTarget);
///
/// 暂停进行中的任务(Active → Paused)。暂停期间目标不推进,失败条件不判定。
/// 非 Active 状态的任务调用此方法无效。
///
void PauseQuest(string questId);
///
/// 恢复已暂停的任务(Paused → Active)。
/// 非 Paused 状态的任务调用此方法无效。
///
void ResumeQuest(string questId);
/// 返回当前任务状态。未知 questId 返回 Unavailable。
QuestStateEnum GetState(string questId);
/// 判断任务是否满足完成条件。
bool IsReadyToComplete(string questId);
/// 返回指定 NPC 的当前好感度数值(未记录时返回 0)。
int GetNpcAffinity(string npcId);
///
/// 返回任务无法被接取的原因(本地化 Key 格式)。
/// 若任务当前可以接取,返回空字符串。
/// Key 格式:"Quest.LockReason.{Reason}";带动态参数时以冒号分隔,如
/// "Quest.LockReason.RequiresQuest:Quest_FindMushroom"。
/// 推荐新代码使用 获取强类型结果,无需手动解析字符串。
///
string GetQuestLockReason(string questId);
///
/// 返回任务无法被接取的强类型锁定信息。
/// 相比 ,可在编译期检查原因枚举,UI 层无需解析字符串。
/// 若任务当前可以接取,返回 为 的实例。
///
QuestLockInfo GetQuestLockInfo(string questId);
///
/// 返回当前处于指定状态的所有任务 ID 快照列表。
/// 适用于任务日志 UI 分组显示、成就系统批量统计等场景。
///
System.Collections.Generic.IReadOnlyList GetQuestsInState(QuestStateEnum state);
///
/// 对所有已注册任务执行谓词过滤,返回满足条件的任务 ID 快照列表。
/// 适用于自定义筛选(如"活跃且含 NPC 亲密度门槛")等场景。
///
System.Collections.Generic.IReadOnlyList FilterQuests(System.Func predicate);
}
///
/// 任务事件订阅接口。
/// 外部系统(成就、地图标记、HUD、埋点)通过此接口订阅任务生命周期事件,
/// 无需直接持有 StringEventChannelSO,保持与 QuestManager 具体实现的解耦。
/// 获取方式:ServiceLocator.Get<IQuestManager>() as IQuestEventSource
///
public interface IQuestEventSource
{
/// 任务成功接取时触发。参数 = questId。
event Action OnQuestStarted;
/// 任务完成时触发。参数 = questId。
event Action OnQuestCompleted;
/// 任务失败时触发。参数 = questId。
event Action OnQuestFailed;
/// 任务被主动放弃时触发。参数 = questId。
event Action OnQuestAbandoned;
/// 任务暂停时触发(Active → Paused)。参数 = questId。供埋点/分析系统使用。
event Action OnQuestPaused;
/// 任务从暂停恢复时触发(Paused → Active)。参数 = questId。供埋点/分析系统使用。
event Action OnQuestResumed;
/// 目标全部达成、可回去交任务时触发(去重,同任务只触发一次)。参数 = questId。
event Action OnQuestReadyToComplete;
///
/// 任务状态发生任意转换时触发(涵盖所有状态变更,含旧状态和新状态)。
/// 供状态机审计面板、通用 UI 绑定(无需分别订阅六个离散事件)使用。
/// 参数:(questId, oldState, newState)。
///
event Action OnQuestStateChanged;
}
#if UNITY_EDITOR || DEVELOPMENT_BUILD
///
/// 任务调试接口(仅编辑器 / 开发构建可用)。
/// 通过 (IQuestManager as IQuestDebugger)?.ResetQuest(id) 使用,
/// 正式发布构建中此接口不存在,调用方无需任何 #if 守卫。
///
public interface IQuestDebugger
{
///
/// 将任务重置为 Available(前置满足)或 Unavailable(前置未满足),并清除目标进度。
/// 不广播 QuestStarted / QuestCompleted 等运行时事件,仅用于开发/调试。
///
/// 要重置的任务 ID。
/// 若为 true(默认),同步回滚此任务对应 NPC 的好感度增量,
/// 防止调试期间重复完成导致好感度叠加。
void ResetQuest(string questId, bool rollbackAffinity = true);
}
#endif
}