package cassandra

import (
	"errors"
	"fmt"
)

// ErrorCode 定義錯誤代碼
type ErrorCode string

const (
	// ErrCodeNotFound 表示記錄未找到
	ErrCodeNotFound ErrorCode = "NOT_FOUND"
	// ErrCodeConflict 表示衝突（如唯一鍵衝突）
	ErrCodeConflict ErrorCode = "CONFLICT"
	// ErrCodeInvalidInput 表示輸入參數無效
	ErrCodeInvalidInput ErrorCode = "INVALID_INPUT"
	// ErrCodeMissingPartition 表示缺少 Partition Key
	ErrCodeMissingPartition ErrorCode = "MISSING_PARTITION_KEY"
	// ErrCodeNoFieldsToUpdate 表示沒有欄位需要更新
	ErrCodeNoFieldsToUpdate ErrorCode = "NO_FIELDS_TO_UPDATE"
	// ErrCodeMissingTableName 表示缺少 TableName 方法
	ErrCodeMissingTableName ErrorCode = "MISSING_TABLE_NAME"
	// ErrCodeMissingWhereCondition 表示缺少 WHERE 條件
	ErrCodeMissingWhereCondition ErrorCode = "MISSING_WHERE_CONDITION"
	// ErrCodeSAINotSupported 表示不支援 SAI
	ErrCodeSAINotSupported ErrorCode = "SAI_NOT_SUPPORTED"
)

// Error 是統一的錯誤類型
type Error struct {
	Code    ErrorCode
	Message string
	Table   string
	Err     error
}

// Error 實現 error 介面
func (e *Error) Error() string {
	if e.Table != "" {
		if e.Err != nil {
			return fmt.Sprintf("cassandra[%s] (table: %s): %s: %v", e.Code, e.Table, e.Message, e.Err)
		}
		return fmt.Sprintf("cassandra[%s] (table: %s): %s", e.Code, e.Table, e.Message)
	}
	if e.Err != nil {
		return fmt.Sprintf("cassandra[%s]: %s: %v", e.Code, e.Message, e.Err)
	}
	return fmt.Sprintf("cassandra[%s]: %s", e.Code, e.Message)
}

// Unwrap 返回底層錯誤
func (e *Error) Unwrap() error {
	return e.Err
}

// WithTable 為錯誤添加表名資訊
func (e *Error) WithTable(table string) *Error {
	return &Error{
		Code:    e.Code,
		Message: e.Message,
		Table:   table,
		Err:     e.Err,
	}
}

// WithError 為錯誤添加底層錯誤
func (e *Error) WithError(err error) *Error {
	return &Error{
		Code:    e.Code,
		Message: e.Message,
		Table:   e.Table,
		Err:     err,
	}
}

// NewError 創建新的錯誤
func NewError(code ErrorCode, message string) *Error {
	return &Error{
		Code:    code,
		Message: message,
	}
}

// 預定義錯誤
var (
	// ErrNotFound 表示記錄未找到
	ErrNotFound = &Error{
		Code:    ErrCodeNotFound,
		Message: "record not found",
	}

	// ErrInvalidInput 表示輸入參數無效
	ErrInvalidInput = &Error{
		Code:    ErrCodeInvalidInput,
		Message: "invalid input parameter",
	}

	// ErrNoPartitionKey 表示缺少 Partition Key
	ErrNoPartitionKey = &Error{
		Code:    ErrCodeMissingPartition,
		Message: "no partition key defined in struct",
	}

	// ErrMissingTableName 表示缺少 TableName 方法
	ErrMissingTableName = &Error{
		Code:    ErrCodeMissingTableName,
		Message: "struct must implement TableName() method",
	}

	// ErrNoFieldsToUpdate 表示沒有欄位需要更新
	ErrNoFieldsToUpdate = &Error{
		Code:    ErrCodeNoFieldsToUpdate,
		Message: "no fields to update",
	}

	// ErrMissingWhereCondition 表示缺少 WHERE 條件
	ErrMissingWhereCondition = &Error{
		Code:    ErrCodeMissingWhereCondition,
		Message: "operation requires at least one WHERE condition for safety",
	}

	// ErrMissingPartitionKey 表示 WHERE 條件中缺少 Partition Key
	ErrMissingPartitionKey = &Error{
		Code:    ErrCodeMissingPartition,
		Message: "operation requires all partition keys in WHERE clause",
	}
	// ErrSAINotSupported 表示不支援 SAI
	ErrSAINotSupported = &Error{
		Code:    ErrCodeSAINotSupported,
		Message: "SAI (Storage-Attached Indexing) is not supported in this Cassandra version",
	}
)

// IsNotFound 檢查錯誤是否為 NotFound
func IsNotFound(err error) bool {
	var e *Error
	if errors.As(err, &e) {
		return e.Code == ErrCodeNotFound
	}
	return false
}

// IsConflict 檢查錯誤是否為 Conflict
func IsConflict(err error) bool {
	var e *Error
	if errors.As(err, &e) {
		return e.Code == ErrCodeConflict
	}
	return false
}
