using System.Collections.Generic;
using System.Data.Common;
using System.Threading.Tasks;
using GB5Shared.DTO.Framework.Login;
using GB5Shared.DTO.WorkFlow;
using static GB5Shared.DTO.WorkFlow.ContractsDTO;
namespace GB5Shared.WorkFlow.WorkFlowEngine
{
public interface IWorkFlowEngine
{
///
/// Facts key injected by EventHandler when login.WipApprovalId > 0.
/// When this key is true, CheckWorkFlowApplicability returns WORKFLOW.NONE,
/// allowing the entity to be saved directly without triggering WIP again.
///
const string WipApprovalFactKey = "__WipApproval";
// ── Applicability check (primary — uses MWORKFLOWCONFIG) ──────────────
///
/// Checks MWORKFLOWCONFIG to determine whether a workflow applies
/// for the given context, and returns the resolved workflow id.
///
/// Steps:
/// 1. Query MWORKFLOWCONFIG filtered by EntityId / ClientId / OUId /
/// BizTransactionClassId / BizTransactionId (wildcards via -1).
/// 2. For each candidate row (most-specific first) evaluate EVALCONDITION
/// against .
/// 3. Return the first match.
/// 4. If Facts["__WipApproval"] == true, returns WORKFLOW.NONE immediately
/// (WIP approval callback — skip all workflow checks).
///
Task CheckWorkFlowApplicability(
WorkflowCheckContext context,
LoginDTO login,
DbTransaction tx);
// ── Start workflow ────────────────────────────────────────────────────
///
/// For REGULAR: creates a workflow instance and tasks for the first approval level.
/// For WIP (IsFormBasedApproval=true): inserts TWORKFLOWWIP, then creates the
/// instance with ObjectId=WipId, then enters the first approval level.
/// Returns a WorkflowStartResult describing what was started.
///
Task StartWorkflowAsync(
WorkflowStartRequest request,
LoginDTO login,
DbTransaction tx);
// ── Action handling ───────────────────────────────────────────────────
///
/// Processes one or more approver actions (Approve / Reject / Return / Escalate).
/// When all tasks at the current approval level are approved the engine
/// automatically advances to the next level and creates tasks there.
/// When no further levels exist the workflow is completed.
/// For WIP instances at final approval: updates TWORKFLOWWIP.STATUS=Approved and
/// returns WipDispatchInfo in WorkflowActionResult.PendingDispatches.
/// Caller MUST dispatch after committing the transaction.
///
Task HandleActionsAsync(
IEnumerable actions,
LoginDTO login,
DbTransaction tx);
// ── Cancel on delete / cancel on resubmit ─────────────────────────────
///
/// Cancels any real pending (WORKFLOWSTATUS=0) workflow instance for the given
/// entity+object — used when the underlying record is deleted, or is about to be
/// resubmitted after an edit while its prior approval is still pending. Cancels the
/// instance's TWORKFLOWTASK rows, the instance itself, its linked TWORKFLOWWIP row
/// (if any), and writes one TWORKFLOWHISTORY entry (Action=Cancel) per cancelled
/// instance. Safe no-op (returns 0) when nothing is pending, e.g. for a new record.
///
Task CancelPendingInstanceAsync(
int entityId,
int objectId,
string reason,
LoginDTO login,
DbTransaction tx);
// ── WIP post-dispatch update ─────────────────────────────────────────
///
/// Called by EventHandler after the WIP approval callback saves the entity.
/// Writes the real saved entity ID (e.g. TaskId) into TWORKFLOWWIP.OBJECTID
/// while still inside the same transaction — so the update is atomic with the
/// entity save and rolls back together if the BLL transaction later fails.
///
Task UpdateWipObjectIdAsync(
int wipId,
int objectId,
LoginDTO login,
DbTransaction tx);
// ── Auto-approve ─────────────────────────────────────────────────────
///
/// Returns all pending tasks whose DUEON has passed and whose step
/// has ISAUTOAPPROVE = 0 (0=Yes). Called by the background auto-approve job.
///
Task> GetOverdueAutoApproveTasksAsync(
LoginDTO login,
DbTransaction tx);
// ── Delegation ────────────────────────────────────────────────────────
///
/// Resolves the effective approver: if the principal has an active delegation
/// record the delegate user-id is returned; otherwise the principal id is used.
///
Task ResolveEffectiveUserAsync(
long userId,
System.DateTime at,
LoginDTO login,
DbTransaction tx);
}
public interface IUserDelegationResolver
{
Task> GetAsync(
long userId,
LoginDTO login,
DbTransaction tx);
}
}