package asynctask

import (
	stderrors "errors"
	"time"
)

// LeaseState 是业务任务持久化层应保存的最小状态与租约事实。
type LeaseState struct {
	Status         int
	LeaseOwner     string
	LeaseExpiresAt *time.Time
}

// ClaimResult 表示条件领取后的新事实。
type ClaimResult struct {
	State   LeaseState
	Claimed bool
}

// Claim 按统一语义判断待处理或租约过期任务能否被领取。
//
// 业务持久化 Adapter 必须把同样的条件放进 PostgreSQL UPDATE 的 WHERE 中；
// 本函数用于跨业务共享状态判定，不能替代数据库条件更新。
func Claim(current LeaseState, owner string, now time.Time, leaseDuration time.Duration) (ClaimResult, error) {
	if owner == "" || leaseDuration <= 0 {
		return ClaimResult{}, stderrors.New("任务租约所有者和时长不能为空")
	}
	claimable := current.Status == StatusPending
	if current.Status == StatusProcessing && current.LeaseExpiresAt != nil && !current.LeaseExpiresAt.After(now) {
		claimable = true
	}
	if !claimable {
		return ClaimResult{State: current}, nil
	}
	expiresAt := now.Add(leaseDuration)
	return ClaimResult{
		State:   LeaseState{Status: StatusProcessing, LeaseOwner: owner, LeaseExpiresAt: &expiresAt},
		Claimed: true,
	}, nil
}

// CanFinish 判断当前租约所有者能否从处理中进入终态。
func CanFinish(current LeaseState, owner string, now time.Time) bool {
	return current.Status == StatusProcessing &&
		current.LeaseOwner == owner &&
		current.LeaseExpiresAt != nil && current.LeaseExpiresAt.After(now)
}

// CanCancel 判断业务支持取消时是否可用预期状态条件更新。
func CanCancel(status int) bool {
	return status == StatusPending || status == StatusProcessing
}
