package datatypes

import (
	
	
	
	
	
	

	
	
	
	
)

// JSONType give a generic data type for json encoded data.
type JSONType[ any] struct {
	data 
}

func [ any]( ) JSONType[] {
	return JSONType[]{
		data: ,
	}
}

// Data return data with generic Type T
func ( JSONType[]) ()  {
	return .data
}

// Value return json value, implement driver.Valuer interface
func ( JSONType[]) () (driver.Value, error) {
	,  := json.Marshal(.data)
	if  != nil {
		return nil, 
	}
	return string(), nil
}

// Scan scan value into JSONType[T], implements sql.Scanner interface
func ( *JSONType[]) ( interface{}) error {
	var  []byte
	switch v := .(type) {
	case []byte:
		 = 
	case string:
		 = []byte()
	default:
		return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", ))
	}
	return json.Unmarshal(, &.data)
}

// MarshalJSON to output non base64 encoded []byte
func ( JSONType[]) () ([]byte, error) {
	return json.Marshal(.data)
}

// UnmarshalJSON to deserialize []byte
func ( *JSONType[]) ( []byte) error {
	return json.Unmarshal(, &.data)
}

// GormDataType gorm common data type
func (JSONType[]) () string {
	return "json"
}

// GormDBDataType gorm db data type
func (JSONType[]) ( *gorm.DB,  *schema.Field) string {
	switch .Dialector.Name() {
	case "sqlite":
		return "JSON"
	case "mysql":
		return "JSON"
	case "postgres":
		return "JSONB"
	}
	return ""
}

func ( JSONType[]) ( context.Context,  *gorm.DB) clause.Expr {
	,  := .MarshalJSON()

	switch .Dialector.Name() {
	case "mysql":
		if ,  := .Dialector.(*mysql.Dialector);  && !strings.Contains(.ServerVersion, "MariaDB") {
			return gorm.Expr("CAST(? AS JSON)", string())
		}
	}

	return gorm.Expr("?", string())
}

// JSONSlice give a generic data type for json encoded slice data.
type JSONSlice[ any] []

func [ any]( []) JSONSlice[] {
	return JSONSlice[]()
}

// Value return json value, implement driver.Valuer interface
func ( JSONSlice[]) () (driver.Value, error) {
	,  := json.Marshal()
	if  != nil {
		return nil, 
	}
	return string(), nil
}

// Scan scan value into JSONType[T], implements sql.Scanner interface
func ( *JSONSlice[]) ( interface{}) error {
	var  []byte
	switch v := .(type) {
	case []byte:
		 = 
	case string:
		 = []byte()
	default:
		return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", ))
	}
	return json.Unmarshal(, &)
}

// GormDataType gorm common data type
func (JSONSlice[]) () string {
	return "json"
}

// GormDBDataType gorm db data type
func (JSONSlice[]) ( *gorm.DB,  *schema.Field) string {
	switch .Dialector.Name() {
	case "sqlite":
		return "JSON"
	case "mysql":
		return "JSON"
	case "postgres":
		return "JSONB"
	}
	return ""
}

func ( JSONSlice[]) ( context.Context,  *gorm.DB) clause.Expr {
	,  := json.Marshal()

	switch .Dialector.Name() {
	case "mysql":
		if ,  := .Dialector.(*mysql.Dialector);  && !strings.Contains(.ServerVersion, "MariaDB") {
			return gorm.Expr("CAST(? AS JSON)", string())
		}
	}

	return gorm.Expr("?", string())
}