package models

import (
	"time"
)

type BulkJobState string
type BulkConcurrencyMode string
type BulkOperation string

const (
	JobStateOpen           BulkJobState = "Open"
	JobStateUploadComplete BulkJobState = "UploadComplete"
	JobStateInProgress     BulkJobState = "InProgress"
	JobStateJobComplete    BulkJobState = "JobComplete"
	JobStateFailed         BulkJobState = "Failed"
	JobStateAborted        BulkJobState = "Aborted"

	ConcurrencyParallel BulkConcurrencyMode = "Parallel"
	ConcurrencySerial   BulkConcurrencyMode = "Serial"

	OperationInsert   BulkOperation = "insert"
	OperationUpdate   BulkOperation = "update"
	OperationUpsert   BulkOperation = "upsert"
	OperationDelete   BulkOperation = "delete"
	OperationQuery    BulkOperation = "query"
	OperationQueryAll BulkOperation = "queryAll"
)

// IsIngest reports whether this operation belongs to the Bulk Ingest API.
// Bulk query jobs share the same persistence table but are owned by a
// different API and lifecycle.
func (o BulkOperation) IsIngest() bool {
	switch o {
	case OperationInsert, OperationUpdate, OperationUpsert, OperationDelete:
		return true
	default:
		return false
	}
}

type BulkJob struct {
	ID              string              `json:"id"`
	Object          string              `json:"object"`
	Operation       BulkOperation       `json:"operation"`
	State           BulkJobState        `json:"state"`
	ConcurrencyMode BulkConcurrencyMode `json:"concurrencyMode"`
	CreatedById     string              `json:"createdById"`
	CreatedDate     time.Time           `json:"createdDate"`
	SystemModstamp  time.Time           `json:"systemModstamp"`
	ErrorMessage    string              `json:"errorMessage,omitempty"`

	// Salesforce-standard fields for wire format parity
	ContentType     string  `json:"contentType"`     // "CSV" (default)
	ColumnDelimiter string  `json:"columnDelimiter"` // "COMMA" (default)
	LineEnding      string  `json:"lineEnding"`      // "LF" (default)
	ApiVersion      float64 `json:"apiVersion"`      // 63.0

	// Query job fields
	JobType    string `json:"jobType,omitempty"`    // V2Ingest or V2Query
	ContentUrl string `json:"contentUrl,omitempty"` // For query jobs, stores SOQL

	// Extended Fields for Upsert and Stats
	ExternalIdFieldName    string `json:"externalIdFieldName,omitempty"`
	NumberRecordsProcessed int    `json:"numberRecordsProcessed"`
	NumberRecordsFailed    int    `json:"numberRecordsFailed"`

	// Stats
	TotalProcessingTime     int64 `json:"totalProcessingTime"`
	ApiActiveProcessingTime int64 `json:"apiActiveProcessingTime"`
	ApexProcessingTime      int64 `json:"apexProcessingTime"`

	// Durable execution facts are persisted with the job but are never exposed
	// through the Salesforce wire shape. WorkBinding freezes the exact metadata
	// view at the first worker claim; the remaining fields form the fenced lease.
	WorkBinding         string     `json:"-"`
	AvailableAt         *time.Time `json:"-"`
	ClaimOwner          string     `json:"-"`
	ClaimToken          string     `json:"-"`
	ClaimOwnershipEpoch uint64     `json:"-"`
	LeaseExpiresAt      *time.Time `json:"-"`
	RetryCount          int        `json:"-"`
	LastFailure         string     `json:"-"`
}

type BulkBatch struct {
	ID               string    `json:"id"`
	JobID            string    `json:"jobId"`
	State            string    `json:"state"` // Queued, InProgress, Completed, Failed
	RecordsProcessed int       `json:"recordsProcessed"`
	RecordsFailed    int       `json:"recordsFailed"`
	TotalRecords     int       `json:"totalRecords"`
	CreatedDate      time.Time `json:"createdDate"`
	SystemModstamp   time.Time `json:"systemModstamp"`

	// Object storage identity and the committed row cursor are the restart
	// boundary for asynchronous execution. They are internal lifecycle facts.
	ObjectKey              string `json:"-"`
	StorageProvider        string `json:"-"`
	StorageBucket          string `json:"-"`
	StorageAuthorityDigest string `json:"-"`
	ContentSHA256          string `json:"-"`
	ContentLength          int64  `json:"-"`
	NextRowOffset          int64  `json:"-"`
	LastError              string `json:"-"`
}
