package packs

import "fmt"

// SourceBackedExecutionAtomIdentity is a packs-minted, non-executable identity
// for one exact execution-atom construction. It exposes neither atom facts nor
// the retained install plan.
type SourceBackedExecutionAtomIdentity struct {
	atom         *SourceBackedExecutionAtom
	construction *SourceBackedPackIdentity
	minted       bool
}

// FreezeSourceBackedExecutionAtomIdentity captures only the exact atom pointer
// and its packs-owned target-construction identity.
func FreezeSourceBackedExecutionAtomIdentity(atom *SourceBackedExecutionAtom) (*SourceBackedExecutionAtomIdentity, error) {
	if err := atom.requireMinted(); err != nil {
		return nil, fmt.Errorf("freeze source-backed execution atom identity: %w", err)
	}
	return &SourceBackedExecutionAtomIdentity{
		atom:         atom,
		construction: atom.identity,
		minted:       true,
	}, nil
}

// ValidateSourceBackedExecutionAtomIdentityTarget confirms that atom is still
// the exact construction captured by identity and still belongs to target.
func ValidateSourceBackedExecutionAtomIdentityTarget(
	identity *SourceBackedExecutionAtomIdentity,
	atom *SourceBackedExecutionAtom,
	target *SourceBackedPack,
) error {
	if err := identity.requireMinted(); err != nil {
		return err
	}
	if err := atom.requireMinted(); err != nil {
		return fmt.Errorf("source-backed execution atom identity target atom: %w", err)
	}
	if identity.atom != atom || identity.construction != atom.identity {
		return fmt.Errorf("source-backed execution atom identity belongs to a different atom")
	}
	if err := ValidateSourceBackedExecutionAtomTarget(atom, target); err != nil {
		return fmt.Errorf("source-backed execution atom identity target: %w", err)
	}
	return nil
}

func (i *SourceBackedExecutionAtomIdentity) requireMinted() error {
	if i == nil || !i.minted || i.atom == nil || i.construction == nil {
		return fmt.Errorf("source-backed execution atom identity was not minted by packs")
	}
	return nil
}
