package models

import (
	"database/sql"
	"time"
)

// SObject represents a generic record
type SObject map[string]interface{}

// Helper methods for SObject
func (s SObject) GetString(key string) string {
	if val, ok := s[key]; ok {
		if str, ok := val.(string); ok {
			return str
		}
	}
	return ""
}

func (s SObject) GetBool(key string) bool {
	if val, ok := s[key]; ok {
		if b, ok := val.(bool); ok {
			return b
		}
	}
	return false
}

func (s SObject) GetTime(key string) time.Time {
	if val, ok := s[key]; ok {
		if t, ok := val.(time.Time); ok {
			return t
		}
		if tStr, ok := val.(string); ok {
			parsed, _ := time.Parse(time.RFC3339, tStr)
			return parsed
		}
	}
	return time.Time{}
}

func (s SObject) Get(key string) interface{} {
	return s[key]
}

// SearchResult represents global search results
// SearchResult represents global search results
type SearchResult struct {
	ObjectLabel   string    `json:"ObjectLabel"`
	ObjectAPIName string    `json:"ObjectApiName"`
	Icon          string    `json:"Icon"`
	Matches       []SObject `json:"Matches"`
}

// AnalyticsQuery represents an analytics query
type AnalyticsQuery struct {
	ObjectAPIName string           `json:"object_api_name"`
	Operation     string           `json:"operation"` // count, sum, avg, group_by
	Field         *string          `json:"field"`
	AggregateType string           `json:"aggregate_type,omitempty"` // SUM, AVG, MIN, MAX (for group_by)
	GroupBy       *string          `json:"group_by"`
	Having        string           `json:"having,omitempty"`      // Raw HAVING clause
	FilterExpr    string           `json:"filter_expr,omitempty"` // Formula expression for filtering
	Criteria      []QueryCriterion `json:"criteria,omitempty"`    // Structured criteria (Preferred)
	SortField     string           `json:"sort_field,omitempty"`
	SortDirection string           `json:"sort_direction,omitempty"`
	Limit         int              `json:"limit,omitempty"` // Optional limit for group_by (default 500)
}

// QueryCriterion represents a single query filter criterion
type QueryCriterion struct {
	Field string      `json:"field"`
	Op    string      `json:"op"`
	Val   interface{} `json:"val"`
}

// SortCriterion represents a sorting condition
type SortCriterion struct {
	Field     string `json:"field"`
	Direction string `json:"direction"`
}

// SubQueryRequest represents a child relationship subquery (e.g., SELECT Id FROM Contacts)
type SubQueryRequest struct {
	RelationshipName string         `json:"relationshipName"`
	SelectFields     []string       `json:"selectFields"`
	FilterExpr       string         `json:"filterExpr,omitempty"`
	OrderBy          []SortCriterion `json:"orderBy,omitempty"`
	Limit            int            `json:"limit,omitempty"`
}

// QueryRequest represents a generic query request
type QueryRequest struct {
	ObjectAPIName string           `json:"object_api_name" binding:"required"`
	Criteria      []QueryCriterion `json:"criteria,omitempty"`
	FilterExpr    string           `json:"filter_expr,omitempty"` // Formula expression for filtering
	SortField     string           `json:"sort_field,omitempty"`
	SortDirection string           `json:"sort_direction,omitempty"`
	Limit         int              `json:"limit,omitempty"`
	Offset        int              `json:"offset,omitempty"`
	ScanAll       bool             `json:"scan_all,omitempty"`
	OrderBy       []SortCriterion  `json:"order_by,omitempty"`
	SelectFields  []string         `json:"select_fields,omitempty"`
	MRUUserID     string           `json:"-"` // When set, JOIN _System_UserRecentItem and ORDER BY AccessedAt DESC
	GroupBy       string           `json:"group_by,omitempty"`
	Having        string           `json:"having,omitempty"`
	SubQueries    []SubQueryRequest `json:"sub_queries,omitempty"`
}

// QueryResult represents the result of a query execution
type QueryResult struct {
	TotalSize      int       `json:"totalSize"`
	Done           bool      `json:"done"`
	Records        []SObject `json:"records"`
	NextRecordsUrl string    `json:"nextRecordsUrl,omitempty"`
}

// SearchRequest represents a search request
type SearchRequest struct {
	Term string `json:"term" binding:"required"`
}

// RecycleBinItem represents an item in the recycle bin
type RecycleBinItem struct {
	ID            string `json:"id"`
	RecordID      string `json:"record_id"`
	ObjectAPIName string `json:"object_api_name"`
	RecordName    string `json:"record_name"`
	DeletedBy     string `json:"deleted_by"`
	DeletedDate   string `json:"deleted_date"`
}

// Transaction represents a database transaction
type Transaction interface {
	Exec(query string, args ...interface{}) (sql.Result, error)
	Query(query string, args ...interface{}) (*sql.Rows, error)
	QueryRow(query string, args ...interface{}) *sql.Row
	Commit() error
	Rollback() error
}
