package files

import (
	"context"
	"crypto/sha256"
	"database/sql"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"strings"
	"time"

	recordfeature "github.com/nexuscrm/backend/internal/features/records"
	"github.com/nexuscrm/backend/internal/infrastructure/storage"
	"github.com/nexuscrm/backend/pkg/apierr"
	"github.com/nexuscrm/backend/pkg/utils"
)

const (
	AttachmentKindArchivedOrder    = "archived_order"
	AttachmentKindArchivedContract = "archived_contract"
	slotKeyArchivedOrder           = "archived_order"
	slotKeyArchivedContract        = "archived_contract"

	uploadStatePrepared   = "PREPARED"
	uploadStateBlobStored = "BLOB_STORED"
	uploadStateCompleted  = "COMPLETED"
	uploadStateFailed     = "FAILED"

	opErrorPutObject = "PUT_OBJECT_FAILED"
	opErrorSwapSlot  = "SWAP_SLOT_FAILED"
	opErrorConflict  = "IDEMPOTENCY_CONFLICT"

	uploadOperationRetryTTL    = 15 * time.Minute
	uploadOperationTerminalTTL = 24 * time.Hour
)

type ObjectStore interface {
	PutObject(ctx context.Context, key string, body io.Reader, opts storage.PutObjectOptions) (storage.ObjectMetadata, error)
	DeleteObject(ctx context.Context, key string) error
}

type ArchivedOrderUploadRequest struct {
	IDempotencyKey      string
	ParentID            string
	ParentObjectAPIName string
	FileName            string
	Extension           string
	MimeType            string
	AttachmentKind      string
	StorageProvider     string
	StorageBucket       string
	Body                io.Reader
	ContentLength       int64
	ContentSHA256       string
	CreatedByID         string
}

type UploadResult struct {
	ID          string
	Name        string
	Size        int64
	Mime        string
	DownloadURL string
}

type ArchivedOrderUploadService struct {
	db    *sql.DB
	store ObjectStore
}

type uploadOperation struct {
	ID             string
	IDempotencyKey string
	RequestHash    string
	State          string
	ObjectKey      string
	SystemFileID   string
	ParentID       string
	ParentObject   string
}

type systemFileRecord struct {
	ID               string
	Name             string
	OriginalFileName string
	MimeType         string
	SizeBytes        int64
	StorageKey       string
	SourceType       string
}

func NewArchivedOrderUploadService(db *sql.DB, store ObjectStore) *ArchivedOrderUploadService {
	if db == nil || store == nil {
		return nil
	}
	return &ArchivedOrderUploadService{db: db, store: store}
}

func (s *ArchivedOrderUploadService) Upload(ctx context.Context, req ArchivedOrderUploadRequest) (UploadResult, error) {
	if s == nil || s.db == nil || s.store == nil {
		return UploadResult{}, apierr.Internal(errors.New("archived order upload service unavailable"))
	}
	if strings.TrimSpace(req.ParentID) == "" || strings.TrimSpace(req.ParentObjectAPIName) == "" {
		return UploadResult{}, apierr.Invalid("parentId and parentObjectApiName are required")
	}
	if strings.TrimSpace(req.FileName) == "" || req.Body == nil {
		return UploadResult{}, apierr.Invalid("file is required")
	}
	req.ParentObjectAPIName = NormalizeParentObjectAPIName(req.ParentID, req.ParentObjectAPIName)
	if strings.TrimSpace(req.AttachmentKind) == "" {
		req.AttachmentKind = AttachmentKindArchivedOrder
	}
	slotKey, err := slotKeyForAttachmentKind(req.AttachmentKind)
	if err != nil {
		return UploadResult{}, apierr.Invalid("unsupported archived upload kind")
	}
	if err := s.validateParentUploadGate(ctx, req, slotKey); err != nil {
		return UploadResult{}, err
	}
	if strings.TrimSpace(req.IDempotencyKey) == "" {
		req.IDempotencyKey = utils.GenerateID()
	}

	requestHash := archivedOrderRequestHash(req)
	op, err := s.getOrCreateOperation(ctx, req, requestHash)
	if err != nil {
		return UploadResult{}, err
	}

	if result, ok, err := s.tryCompleteFromExistingMetadata(ctx, op); err != nil {
		return UploadResult{}, err
	} else if ok {
		return result, nil
	}

	objectKey := systemFileObjectKey(req.ParentObjectAPIName, req.ParentID, op.SystemFileID, req.FileName)
	meta, err := s.store.PutObject(ctx, objectKey, req.Body, storage.PutObjectOptions{
		ContentType:   req.MimeType,
		ContentLength: int64Ptr(req.ContentLength),
	})
	if err != nil {
		s.markOperationFailed(ctx, op.ID, opErrorPutObject, err.Error())
		return UploadResult{}, err
	}
	if err := s.updateOperationProgress(ctx, op.ID, uploadStateBlobStored, objectKey, op.SystemFileID); err != nil {
		s.markOperationFailed(ctx, op.ID, opErrorPutObject, err.Error())
		return UploadResult{}, err
	}

	oldRecord, err := s.replaceArchivedOrderSlot(ctx, op, req, objectKey, meta, slotKey)
	if err != nil {
		s.markOperationFailed(ctx, op.ID, opErrorSwapSlot, err.Error())
		return UploadResult{}, err
	}

	if err := s.updateOperationProgress(ctx, op.ID, uploadStateCompleted, objectKey, op.SystemFileID); err != nil {
		return UploadResult{}, err
	}

	if oldRecord.StorageKey != "" && oldRecord.StorageKey != objectKey && !strings.EqualFold(oldRecord.SourceType, "content_compat") {
		_ = s.store.DeleteObject(ctx, oldRecord.StorageKey)
	}

	return UploadResult{
		ID:          op.SystemFileID,
		Name:        req.FileName,
		Size:        meta.Size,
		Mime:        req.MimeType,
		DownloadURL: recordFileDownloadURL(op.SystemFileID),
	}, nil
}

func (s *ArchivedOrderUploadService) validateParentUploadGate(ctx context.Context, req ArchivedOrderUploadRequest, slotKey string) error {
	if s == nil || s.db == nil {
		return apierr.Internal(errors.New("archived order upload service unavailable"))
	}

	tableName, objectLabel, err := archivedUploadTarget(req.AttachmentKind, req.ParentObjectAPIName)
	if err != nil {
		return err
	}

	row := s.db.QueryRowContext(
		ctx,
		fmt.Sprintf("SELECT `Status`, `Archived__c` FROM `%s` WHERE `Id` = ? LIMIT 1", tableName),
		req.ParentID,
	)

	var status sql.NullString
	var archived sql.NullBool
	if err := row.Scan(&status, &archived); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return apierr.NotFound(fmt.Sprintf("%s with ID '%s' not found", objectLabel, req.ParentID))
		}
		return err
	}

	if strings.EqualFold(strings.TrimSpace(status.String), "Approved") || archived.Bool {
		return nil
	}

	return apierr.Invalid(fmt.Sprintf("%s must be Approved before uploading %s", objectLabel, archivedUploadLabel(slotKey)))
}

func (s *ArchivedOrderUploadService) getOrCreateOperation(ctx context.Context, req ArchivedOrderUploadRequest, requestHash string) (uploadOperation, error) {
	op, err := s.getOperationByIDempotencyKey(ctx, req.IDempotencyKey)
	if err != nil {
		return uploadOperation{}, err
	}
	if op.ID == "" {
		op = uploadOperation{
			ID:             utils.GenerateID(),
			IDempotencyKey: req.IDempotencyKey,
			RequestHash:    requestHash,
			State:          uploadStatePrepared,
			SystemFileID:   utils.GenerateID(),
			ParentID:       req.ParentID,
			ParentObject:   req.ParentObjectAPIName,
		}
		if err := s.insertOperation(ctx, op); err != nil {
			if !isDuplicateKeyError(err) {
				return uploadOperation{}, err
			}
			op, err = s.getOperationByIDempotencyKey(ctx, req.IDempotencyKey)
			if err != nil {
				return uploadOperation{}, err
			}
		}
	}

	if op.RequestHash != "" && op.RequestHash != requestHash {
		s.markOperationFailed(ctx, op.ID, opErrorConflict, "idempotency key reused with a different upload payload")
		return uploadOperation{}, apierr.Conflict("idempotency key reused with a different upload payload")
	}

	if op.SystemFileID == "" {
		op.SystemFileID = utils.GenerateID()
	}
	if op.ParentID == "" {
		op.ParentID = req.ParentID
	}
	if op.ParentObject == "" {
		op.ParentObject = req.ParentObjectAPIName
	}
	if err := s.resetOperationForRetry(ctx, op, requestHash); err != nil {
		return uploadOperation{}, err
	}
	op.RequestHash = requestHash
	op.State = uploadStatePrepared
	return op, nil
}

func (s *ArchivedOrderUploadService) tryCompleteFromExistingMetadata(ctx context.Context, op uploadOperation) (UploadResult, bool, error) {
	if strings.TrimSpace(op.SystemFileID) == "" {
		return UploadResult{}, false, nil
	}

	record, err := s.getSystemFileByID(ctx, op.SystemFileID)
	if err != nil {
		return UploadResult{}, false, err
	}
	if record.ID == "" {
		return UploadResult{}, false, nil
	}

	if err := s.updateOperationProgress(ctx, op.ID, uploadStateCompleted, record.StorageKey, op.SystemFileID); err != nil {
		return UploadResult{}, false, err
	}

	name := record.OriginalFileName
	if strings.TrimSpace(name) == "" {
		name = record.Name
	}

	return UploadResult{
		ID:          record.ID,
		Name:        name,
		Size:        record.SizeBytes,
		Mime:        record.MimeType,
		DownloadURL: recordFileDownloadURL(record.ID),
	}, true, nil
}

func (s *ArchivedOrderUploadService) replaceArchivedOrderSlot(
	ctx context.Context,
	op uploadOperation,
	req ArchivedOrderUploadRequest,
	objectKey string,
	meta storage.ObjectMetadata,
	slotKey string,
) (systemFileRecord, error) {
	tx, err := s.db.BeginTx(ctx, nil)
	if err != nil {
		return systemFileRecord{}, err
	}
	defer func() {
		if tx != nil {
			_ = tx.Rollback()
		}
	}()

	oldRecord, err := s.lockSlotRecord(ctx, tx, req.ParentObjectAPIName, req.ParentID, slotKey)
	if err != nil {
		return systemFileRecord{}, err
	}

	if oldRecord.ID != "" && oldRecord.ID != op.SystemFileID {
		if _, err := tx.ExecContext(ctx, "DELETE FROM `_System_File` WHERE `Id` = ?", oldRecord.ID); err != nil {
			return systemFileRecord{}, translateSlotConflict(err)
		}
	}

	if oldRecord.ID == op.SystemFileID {
		if err := tx.Commit(); err != nil {
			return systemFileRecord{}, err
		}
		tx = nil
		return oldRecord, nil
	}

	_, err = tx.ExecContext(
		ctx,
		"INSERT INTO `_System_File` ("+
			"`Id`, `ParentId`, `ParentObjectApiName`, `Name`, `OriginalFileName`, `Extension`, "+
			"`MimeType`, `SizeBytes`, `StoragePath`, `StorageProvider`, `StorageBucket`, `StorageKey`, "+
			"`Status`, `SourceType`, `AttachmentKind`, `SlotKey`, `CreatedById`"+
			") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
		op.SystemFileID,
		req.ParentID,
		req.ParentObjectAPIName,
		req.FileName,
		req.FileName,
		strings.TrimPrefix(req.Extension, "."),
		req.MimeType,
		meta.Size,
		objectKey,
		req.StorageProvider,
		req.StorageBucket,
		objectKey,
		"Active",
		"native",
		req.AttachmentKind,
		slotKey,
		req.CreatedByID,
	)
	if err != nil {
		return systemFileRecord{}, translateSlotConflict(err)
	}

	if err := applyArchivedUploadParentUpdates(ctx, tx, req, op.SystemFileID); err != nil {
		return systemFileRecord{}, err
	}

	if err := tx.Commit(); err != nil {
		return systemFileRecord{}, err
	}
	tx = nil
	return oldRecord, nil
}

func (s *ArchivedOrderUploadService) getOperationByIDempotencyKey(ctx context.Context, idempotencyKey string) (uploadOperation, error) {
	row := s.db.QueryRowContext(
		ctx,
		"SELECT `Id`, `IdempotencyKey`, `RequestHash`, `State`, `ObjectKey`, `SystemFileId`, `ParentId`, `ParentObjectApiName` "+
			"FROM `_System_FileUploadOperation` "+
			"WHERE `IdempotencyKey` = ? "+
			"LIMIT 1",
		idempotencyKey,
	)

	var op uploadOperation
	if err := row.Scan(&op.ID, &op.IDempotencyKey, &op.RequestHash, &op.State, &op.ObjectKey, &op.SystemFileID, &op.ParentID, &op.ParentObject); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return uploadOperation{}, nil
		}
		return uploadOperation{}, err
	}
	return op, nil
}

func (s *ArchivedOrderUploadService) insertOperation(ctx context.Context, op uploadOperation) error {
	expiresAt := uploadOperationExpiresAt(uploadStatePrepared, time.Now().UTC())
	_, err := s.db.ExecContext(
		ctx,
		"INSERT INTO `_System_FileUploadOperation` ("+
			"`Id`, `IdempotencyKey`, `RequestHash`, `State`, `ObjectKey`, `SystemFileId`, `ParentId`, `ParentObjectApiName`, `ExpiresAt`"+
			") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
		op.ID,
		op.IDempotencyKey,
		op.RequestHash,
		op.State,
		op.ObjectKey,
		op.SystemFileID,
		op.ParentID,
		op.ParentObject,
		expiresAt,
	)
	return err
}

func (s *ArchivedOrderUploadService) resetOperationForRetry(ctx context.Context, op uploadOperation, requestHash string) error {
	expiresAt := uploadOperationExpiresAt(uploadStatePrepared, time.Now().UTC())
	_, err := s.db.ExecContext(
		ctx,
		"UPDATE `_System_FileUploadOperation` "+
			"SET `RequestHash` = ?, `State` = ?, `ErrorCode` = NULL, `ErrorMessage` = NULL, "+
			"`SystemFileId` = ?, `ParentId` = ?, `ParentObjectApiName` = ?, `ExpiresAt` = ?, `LastModifiedDate` = CURRENT_TIMESTAMP "+
			"WHERE `Id` = ?",
		requestHash,
		uploadStatePrepared,
		op.SystemFileID,
		op.ParentID,
		op.ParentObject,
		expiresAt,
		op.ID,
	)
	return err
}

func (s *ArchivedOrderUploadService) updateOperationProgress(ctx context.Context, operationID, state, objectKey, systemFileID string) error {
	expiresAt := uploadOperationExpiresAt(state, time.Now().UTC())
	_, err := s.db.ExecContext(
		ctx,
		"UPDATE `_System_FileUploadOperation` "+
			"SET `State` = ?, `ObjectKey` = ?, `SystemFileId` = ?, `ErrorCode` = NULL, "+
			"`ErrorMessage` = NULL, `ExpiresAt` = ?, `LastModifiedDate` = CURRENT_TIMESTAMP "+
			"WHERE `Id` = ?",
		state,
		objectKey,
		systemFileID,
		expiresAt,
		operationID,
	)
	return err
}

func (s *ArchivedOrderUploadService) markOperationFailed(ctx context.Context, operationID, errorCode, errorMessage string) {
	if strings.TrimSpace(operationID) == "" {
		return
	}
	_, _ = s.db.ExecContext(
		ctx,
		"UPDATE `_System_FileUploadOperation` "+
			"SET `State` = ?, `ErrorCode` = ?, `ErrorMessage` = ?, `ExpiresAt` = ?, `LastModifiedDate` = CURRENT_TIMESTAMP "+
			"WHERE `Id` = ?",
		uploadStateFailed,
		errorCode,
		errorMessage,
		uploadOperationExpiresAt(uploadStateFailed, time.Now().UTC()),
		operationID,
	)
}

func uploadOperationExpiresAt(state string, now time.Time) time.Time {
	if now.IsZero() {
		now = time.Now().UTC()
	}
	switch strings.ToUpper(strings.TrimSpace(state)) {
	case uploadStateCompleted, uploadStateFailed:
		return now.Add(uploadOperationTerminalTTL)
	default:
		return now.Add(uploadOperationRetryTTL)
	}
}

func (s *ArchivedOrderUploadService) getSystemFileByID(ctx context.Context, fileID string) (systemFileRecord, error) {
	row := s.db.QueryRowContext(
		ctx,
		"SELECT `Id`, `Name`, `OriginalFileName`, `MimeType`, `SizeBytes`, `StorageKey`, `SourceType` "+
			"FROM `_System_File` "+
			"WHERE `Id` = ? "+
			"LIMIT 1",
		fileID,
	)

	var record systemFileRecord
	if err := row.Scan(&record.ID, &record.Name, &record.OriginalFileName, &record.MimeType, &record.SizeBytes, &record.StorageKey, &record.SourceType); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return systemFileRecord{}, nil
		}
		return systemFileRecord{}, err
	}
	return record, nil
}

func (s *ArchivedOrderUploadService) lockSlotRecord(ctx context.Context, tx *sql.Tx, parentObjectAPIName, parentID, slotKey string) (systemFileRecord, error) {
	row := tx.QueryRowContext(
		ctx,
		"SELECT `Id`, `Name`, `OriginalFileName`, `MimeType`, `SizeBytes`, `StorageKey`, `SourceType` "+
			"FROM `_System_File` "+
			"WHERE `ParentObjectApiName` = ? AND `ParentId` = ? AND `SlotKey` = ? "+
			"LIMIT 1 FOR UPDATE",
		parentObjectAPIName,
		parentID,
		slotKey,
	)

	var record systemFileRecord
	if err := row.Scan(&record.ID, &record.Name, &record.OriginalFileName, &record.MimeType, &record.SizeBytes, &record.StorageKey, &record.SourceType); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return systemFileRecord{}, nil
		}
		return systemFileRecord{}, err
	}
	return record, nil
}

func archivedOrderRequestHash(req ArchivedOrderUploadRequest) string {
	sum := sha256.Sum256([]byte(strings.Join([]string{
		strings.TrimSpace(req.ParentID),
		strings.TrimSpace(req.ParentObjectAPIName),
		strings.TrimSpace(req.AttachmentKind),
		strings.TrimSpace(req.FileName),
		strings.TrimPrefix(strings.TrimSpace(req.Extension), "."),
		strings.TrimSpace(req.MimeType),
		fmt.Sprintf("%d", req.ContentLength),
		strings.TrimSpace(req.ContentSHA256),
	}, "|")))
	return hex.EncodeToString(sum[:])
}

func applyArchivedUploadParentUpdates(ctx context.Context, tx *sql.Tx, req ArchivedOrderUploadRequest, systemFileID string) error {
	switch strings.ToLower(strings.TrimSpace(req.AttachmentKind)) {
	case AttachmentKindArchivedOrder:
		shouldActivate, currentStatus, err := archivedOrderShouldActivate(ctx, tx, req.ParentID)
		if err != nil {
			return err
		}
		if shouldActivate {
			_, err = tx.ExecContext(
				ctx,
				"UPDATE `Order` SET `Status` = ?, `StatusCode` = ?, `ActivatedDate` = CURRENT_TIMESTAMP, `ActivatedById` = ?, `StandardUploadUrl__c` = ?, `Archived_Order_Form__c` = ?, `Archived__c` = 1 WHERE `Id` = ?",
				"Activated",
				"Activated",
				req.CreatedByID,
				recordFileDownloadURL(systemFileID),
				req.FileName,
				req.ParentID,
			)
			return err
		}

		updates := []string{
			"`StandardUploadUrl__c` = ?",
			"`Archived_Order_Form__c` = ?",
			"`Archived__c` = 1",
		}
		args := []any{
			recordFileDownloadURL(systemFileID),
			req.FileName,
		}
		if strings.EqualFold(currentStatus, "Activated") {
			updates = append([]string{
				"`Status` = ?",
				"`StatusCode` = ?",
			}, updates...)
			args = append([]any{"Activated", "Activated"}, args...)
		}
		args = append(args, req.ParentID)
		_, err = tx.ExecContext(
			ctx,
			fmt.Sprintf("UPDATE `Order` SET %s WHERE `Id` = ?", strings.Join(updates, ", ")),
			args...,
		)
		return err
	case AttachmentKindArchivedContract:
		_, err := tx.ExecContext(
			ctx,
			"UPDATE `Contract` SET `Status` = ?, `Archived__c` = 1 WHERE `Id` = ?",
			"Effective",
			req.ParentID,
		)
		return err
	default:
		return apierr.Invalid("unsupported archived upload kind")
	}
}

func archivedOrderShouldActivate(ctx context.Context, tx *sql.Tx, orderID string) (bool, string, error) {
	row := tx.QueryRowContext(
		ctx,
		"SELECT `Status`, `ContractId`, `EffectiveDate`, `EndDate` FROM `Order` WHERE `Id` = ? LIMIT 1 FOR UPDATE",
		orderID,
	)

	var status sql.NullString
	var contractID sql.NullString
	var effectiveDate sql.NullString
	var endDate sql.NullString
	if err := row.Scan(&status, &contractID, &effectiveDate, &endDate); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return false, "", apierr.NotFound(fmt.Sprintf("Order with ID '%s' not found", orderID))
		}
		return false, "", err
	}

	currentStatus := strings.TrimSpace(status.String)
	if strings.EqualFold(currentStatus, "Activated") {
		return false, currentStatus, nil
	}
	if !strings.EqualFold(currentStatus, "Approved") {
		return false, currentStatus, nil
	}

	if strings.TrimSpace(contractID.String) == "" {
		return false, currentStatus, nil
	}

	contractRow := tx.QueryRowContext(
		ctx,
		"SELECT `Status`, `StartDate`, `EndDate` FROM `Contract` WHERE `Id` = ? LIMIT 1",
		strings.TrimSpace(contractID.String),
	)

	var contractStatus sql.NullString
	var contractStartDate sql.NullString
	var contractEndDate sql.NullString
	if err := contractRow.Scan(&contractStatus, &contractStartDate, &contractEndDate); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return false, currentStatus, nil
		}
		return false, currentStatus, err
	}

	if err := recordfeature.ValidateOrderActivationContractWindow(
		contractStatus.String,
		effectiveDate.String,
		endDate.String,
		contractStartDate.String,
		contractEndDate.String,
	); err != nil {
		var invalidErr *apierr.Error
		if errors.As(err, &invalidErr) && invalidErr.Code == "InvalidRequest" {
			return false, currentStatus, nil
		}
		return false, currentStatus, err
	}

	return true, currentStatus, nil
}

func recordFileDownloadURL(fileID string) string {
	return fmt.Sprintf("/services/data/v63.0/files/%s/download", fileID)
}

func systemFileObjectKey(parentObjectAPIName, parentID, systemFileID, fileName string) string {
	return fmt.Sprintf("system-file/%s/%s/%s/%s",
		strings.TrimSpace(parentObjectAPIName),
		strings.TrimSpace(parentID),
		strings.TrimSpace(systemFileID),
		sanitizeUploadedFileName(fileName),
	)
}

func sanitizeUploadedFileName(name string) string {
	safe := strings.Map(func(r rune) rune {
		switch r {
		case '/', '\\':
			return -1
		default:
			return r
		}
	}, strings.TrimSpace(name))
	if safe == "" {
		return fmt.Sprintf("upload-%d", time.Now().UnixNano())
	}
	return safe
}

func translateSlotConflict(err error) error {
	if err == nil {
		return nil
	}
	if isDuplicateKeyError(err) {
		return apierr.Conflict("another archived file upload is in progress; retry the upload")
	}
	return err
}

func slotKeyForAttachmentKind(kind string) (string, error) {
	switch strings.ToLower(strings.TrimSpace(kind)) {
	case AttachmentKindArchivedOrder:
		return slotKeyArchivedOrder, nil
	case AttachmentKindArchivedContract:
		return slotKeyArchivedContract, nil
	default:
		return "", fmt.Errorf("unsupported attachment kind: %s", kind)
	}
}

func archivedUploadTarget(kind, parentObjectAPIName string) (tableName string, objectLabel string, err error) {
	switch strings.ToLower(strings.TrimSpace(kind)) {
	case AttachmentKindArchivedOrder:
		if !strings.EqualFold(strings.TrimSpace(parentObjectAPIName), "Order") {
			return "", "", apierr.Invalid("archived order uploads must target Order records")
		}
		return "Order", "Order", nil
	case AttachmentKindArchivedContract:
		if !strings.EqualFold(strings.TrimSpace(parentObjectAPIName), "Contract") {
			return "", "", apierr.Invalid("archived contract uploads must target Contract records")
		}
		return "Contract", "Contract", nil
	default:
		return "", "", apierr.Invalid("unsupported archived upload kind")
	}
}

func archivedUploadLabel(slotKey string) string {
	switch strings.ToLower(strings.TrimSpace(slotKey)) {
	case slotKeyArchivedOrder:
		return "an archived order form"
	case slotKeyArchivedContract:
		return "an archived contract"
	default:
		return "an archived file"
	}
}

func isDuplicateKeyError(err error) bool {
	if err == nil {
		return false
	}
	msg := strings.ToLower(err.Error())
	return strings.Contains(msg, "duplicate") || strings.Contains(msg, "unique") || strings.Contains(msg, "1062")
}

func int64Ptr(v int64) *int64 {
	return &v
}
