package ports

import "errors"

// ErrUniqueFieldUpsertRace marks a create attempt that lost the database
// uniqueness race on the exact unique field used by UpsertByExternalID.
//
// The records layer emits this only after classifying the conflicting unique
// index. Transaction owners may then roll back the entire attempt and replay
// it, so before-save effects from the losing INSERT cannot leak into the
// adopted winner's transaction.
var ErrUniqueFieldUpsertRace = errors.New("unique-field upsert lost concurrent create race")

// ErrExternalIDUpsertAdoptionGuardConflict marks an atomic external-ID upsert
// that found the requested external identity, but refused to adopt its row
// because a non-blank ownership guard belongs to a different claimant.
//
// Automation may route this one semantic outcome to a quarantine branch. It
// must not classify ordinary validation, permission, infrastructure, or
// uniqueness errors as safe adoption conflicts.
var ErrExternalIDUpsertAdoptionGuardConflict = errors.New("external-ID upsert adoption guard conflict")

// ErrDatabaseDuplicateKey marks a ConflictError that originated from the
// database rejecting an INSERT or UPDATE with a duplicate-key violation.
// Business-layer uniqueness prechecks deliberately do not carry this marker.
// Callers still need operation-local provenance before treating it as a
// replay-safe create race or guarded-adoption conflict.
var ErrDatabaseDuplicateKey = errors.New("database rejected mutation with duplicate key")

// IsUniqueFieldUpsertRace reports whether err carries the replay-safe unique
// field race marker.
func IsUniqueFieldUpsertRace(err error) bool {
	return errors.Is(err, ErrUniqueFieldUpsertRace)
}

// IsExternalIDUpsertAdoptionGuardConflict reports whether err is the precise
// guarded-adoption refusal emitted by the records layer.
func IsExternalIDUpsertAdoptionGuardConflict(err error) bool {
	return errors.Is(err, ErrExternalIDUpsertAdoptionGuardConflict)
}

// IsDatabaseDuplicateKey reports whether err carries database duplicate-key
// provenance in addition to its public ConflictError shape.
func IsDatabaseDuplicateKey(err error) bool {
	return errors.Is(err, ErrDatabaseDuplicateKey)
}
