package models

import (
	"encoding/json"
	"time"
)

// ToSObject converts SystemAuditLog to SObject
func (a *SystemAuditLog) ToSObject() SObject {
	b, _ := json.Marshal(a)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts SystemLog to SObject
func (l *SystemLog) ToSObject() SObject {
	b, _ := json.Marshal(l)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts SystemConfig to SObject
func (c *SystemConfig) ToSObject() SObject {
	b, _ := json.Marshal(c)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts SystemTable to SObject
func (t *SystemTable) ToSObject() SObject {
	b, _ := json.Marshal(t)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts Notification to SObject
func (n *Notification) ToSObject() SObject {
	b, _ := json.Marshal(n)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts User to SObject
func (u *User) ToSObject() SObject {
	b, _ := json.Marshal(u)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	// Manually add password as it is hidden from JSON
	if u.Password != "" {
		m["password"] = u.Password
	}
	return m
}

// ToSObject converts SystemSession to SObject
func (s *SystemSession) ToSObject() SObject {
	b, _ := json.Marshal(s)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts SystemComment to SObject
func (c *SystemComment) ToSObject() SObject {
	b, _ := json.Marshal(c)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts SystemFile to SObject
func (f *SystemFile) ToSObject() SObject {
	b, _ := json.Marshal(f)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts Profile to SObject
func (p *Profile) ToSObject() SObject {
	b, _ := json.Marshal(p)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts SystemRecent to SObject
func (r *SystemRecent) ToSObject() SObject {
	b, _ := json.Marshal(r)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts UserRole to SObject
func (r *UserRole) ToSObject() SObject {
	b, _ := json.Marshal(r)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts Group to SObject
func (g *Group) ToSObject() SObject {
	b, _ := json.Marshal(g)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts PermissionSet to SObject
func (p *PermissionSet) ToSObject() SObject {
	b, _ := json.Marshal(p)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts SharingRule to SObject
func (s *SharingRule) ToSObject() SObject {
	b, _ := json.Marshal(s)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts ObjectPermissions to SObject
func (p *ObjectPermissions) ToSObject() SObject {
	b, _ := json.Marshal(p)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// ToSObject converts FieldPermissions to SObject
func (p *FieldPermissions) ToSObject() SObject {
	b, _ := json.Marshal(p)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// OutboxEvent represents a persisted event record
type OutboxEvent struct {
	ID               string     `json:"id"`
	EventType        string     `json:"event_type"`
	Payload          string     `json:"payload"` // JSON string
	Status           string     `json:"status"`
	RetryCount       int        `json:"retry_count"`
	RecordKey        string     `json:"record_key,omitempty"`
	ErrorMessage     string     `json:"error_message"`
	CreatedDate      time.Time  `json:"created_date"`
	ProcessedDate    *time.Time `json:"processed_date"`
	LastModifiedDate time.Time  `json:"last_modified_date"`
}

// OutboxClaim is the durable generation identity of one processing attempt.
// Token is empty only for legacy in-process repositories whose claim and effect
// share one transaction. Independently deployed pull workers must persist a
// fresh token on every claim and use the complete handle for heartbeat,
// completion, and retry transitions. RetryCount is read from the claimed
// durable row after the claim transition; discovery results are not attempt
// authority. The handle is not authority by itself: Persistence must also
// prove that its database-owned lease is still live before admitting effects
// or renewing the attempt.
type OutboxClaim struct {
	EventID    string
	Token      string
	RetryCount int
	// RecordKey selects the stable deployment-fence slot for this attempt. It
	// is derived from the immutable durable payload (falling back to EventID),
	// never from worker or replica identity.
	RecordKey string
}

// ToSObject converts OutboxEvent to SObject
func (e *OutboxEvent) ToSObject() SObject {
	b, _ := json.Marshal(e)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	return m
}

// SystemReportType represents the _System_ReportType table — the stored
// Custom Report Type definitions consumed by the analytics CRT synthesizer.
// The JSON-typed columns (Sections, Join, Metadata) are kept as raw strings
// so the parser layer can enforce its own nil-tolerant handling rather than
// conflating missing with malformed at unmarshal time.
type SystemReportType struct {
	ID               string    `json:"Id"`
	FullName         string    `json:"FullName"`
	Label            string    `json:"Label"`
	Description      string    `json:"Description,omitempty"`
	BaseObject       string    `json:"BaseObject"`
	Deployed         bool      `json:"Deployed"`
	Autogenerated    bool      `json:"Autogenerated"`
	Sections         string    `json:"Sections,omitempty"`
	Categories       string    `json:"Categories,omitempty"`
	Join             string    `json:"Join,omitempty"`
	Metadata         string    `json:"Metadata,omitempty"`
	OwnerPack        string    `json:"OwnerPack,omitempty"`
	CreatedDate      time.Time `json:"CreatedDate"`
	LastModifiedDate time.Time `json:"LastModifiedDate"`
}

// GetTableName returns the database table name for SystemReportType.
func (SystemReportType) GetTableName() string {
	return "_System_ReportType"
}
