// Package package 提供套餐生命周期领域规则。
package packagedomain

import (
	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
)

// TermsSnapshot 套餐购买时不可变计时条款。
type TermsSnapshot struct {
	ExpiryBase     string
	CalendarType   string
	DurationMonths int
	DurationDays   int
}

// ResolveTermsSnapshot 解析并校验套餐购买时计时条款。
func ResolveTermsSnapshot(pkg *model.Package, allocation *model.ShopPackageAllocation) (TermsSnapshot, error) {
	if pkg == nil {
		return TermsSnapshot{}, errors.New(errors.CodeInvalidParam, "套餐计时条款缺失")
	}
	expiryBase := pkg.ExpiryBase
	if allocation != nil && allocation.ExpiryBaseOverride != nil {
		expiryBase = *allocation.ExpiryBaseOverride
	}
	if expiryBase != constants.PackageExpiryBaseFromActivation && expiryBase != constants.PackageExpiryBaseFromPurchase {
		return TermsSnapshot{}, errors.New(errors.CodeInvalidParam, "套餐生效条件无效")
	}
	if pkg.CalendarType == constants.PackageCalendarTypeNaturalMonth {
		if pkg.DurationMonths <= 0 {
			return TermsSnapshot{}, errors.New(errors.CodeInvalidParam, "套餐自然月时长无效")
		}
		return TermsSnapshot{ExpiryBase: expiryBase, CalendarType: pkg.CalendarType, DurationMonths: pkg.DurationMonths}, nil
	}
	if pkg.CalendarType == constants.PackageCalendarTypeByDay && pkg.DurationDays > 0 {
		return TermsSnapshot{ExpiryBase: expiryBase, CalendarType: pkg.CalendarType, DurationDays: pkg.DurationDays}, nil
	}
	return TermsSnapshot{}, errors.New(errors.CodeInvalidParam, "套餐按天时长无效")
}

// Apply 将计时条款写入套餐使用记录。
func (s TermsSnapshot) Apply(usage *model.PackageUsage) {
	usage.ExpiryBaseSnapshot = s.ExpiryBase
	usage.CalendarTypeSnapshot = s.CalendarType
	usage.DurationMonthsSnapshot = s.DurationMonths
	usage.DurationDaysSnapshot = s.DurationDays
}

// IsValid 判断快照是否完整有效。
func (s TermsSnapshot) IsValid() bool {
	if s.ExpiryBase != constants.PackageExpiryBaseFromActivation && s.ExpiryBase != constants.PackageExpiryBaseFromPurchase {
		return false
	}
	return (s.CalendarType == constants.PackageCalendarTypeNaturalMonth && s.DurationMonths > 0) ||
		(s.CalendarType == constants.PackageCalendarTypeByDay && s.DurationDays > 0)
}

// TermsSnapshotFromUsage 从使用记录读取计时条款。
func TermsSnapshotFromUsage(usage *model.PackageUsage) TermsSnapshot {
	return TermsSnapshot{
		ExpiryBase: usage.ExpiryBaseSnapshot, CalendarType: usage.CalendarTypeSnapshot,
		DurationMonths: usage.DurationMonthsSnapshot, DurationDays: usage.DurationDaysSnapshot,
	}
}
