package Models

import (
	"database/sql/driver"
	"errors"

	"github.com/gofrs/uuid"
	"gorm.io/gorm"
)

// BeforeUpdate prevents updating the email if it has not changed
// This stops a unique constraint error
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
	if !tx.Statement.Changed("Username") {
		tx.Statement.Omit("Username")
	}
	return nil
}

// MessageExpiry holds values for how long messages should expire by default
type MessageExpiry []uint8

const (
	// MessageExpiryFifteenMin expires after 15 minutes
	MessageExpiryFifteenMin = "fifteen_min"
	// MessageExpiryThirtyMin expires after 30 minutes
	MessageExpiryThirtyMin = "thirty_min"
	// MessageExpiryOneHour expires after one hour
	MessageExpiryOneHour = "one_hour"
	// MessageExpiryThreeHour expires after three hours
	MessageExpiryThreeHour = "three_hour"
	// MessageExpirySixHour expires after six hours
	MessageExpirySixHour = "six_hour"
	// MessageExpiryTwelveHour expires after twelve hours
	MessageExpiryTwelveHour = "twelve_hour"
	// MessageExpiryOneDay expires after one day
	MessageExpiryOneDay = "one_day"
	// MessageExpiryThreeDay expires after three days
	MessageExpiryThreeDay = "three_day"
	// MessageExpiryNoExpiry never expires
	MessageExpiryNoExpiry = "no_expiry"
)

// MessageExpiryValues list of all expiry values for validation
var MessageExpiryValues = []string{
	MessageExpiryFifteenMin,
	MessageExpiryThirtyMin,
	MessageExpiryOneHour,
	MessageExpiryThreeHour,
	MessageExpirySixHour,
	MessageExpiryTwelveHour,
	MessageExpiryOneDay,
	MessageExpiryThreeDay,
	MessageExpiryNoExpiry,
}

// Scan new value into MessageExpiry
func (e *MessageExpiry) Scan(value interface{}) error {
	var (
		strValue = value.(string)
		m        string
	)

	for _, m = range MessageExpiryValues {
		if strValue != m {
			continue
		}
		*e = MessageExpiry(strValue)
		return nil
	}

	return errors.New("Invalid MessageExpiry value")
}

// Value gets value out of MessageExpiry column
func (e MessageExpiry) Value() (driver.Value, error) {
	return string(e), nil
}

func (e MessageExpiry) String() string {
	return string(e)
}

// User holds user data
type User struct {
	Base
	Username             string        `gorm:"not null;unique"   json:"username"`
	Password             string        `gorm:"not null"          json:"password"`
	ConfirmPassword      string        `gorm:"-"                 json:"confirm_password"`
	AsymmetricPrivateKey string        `gorm:"not null"          json:"asymmetric_private_key"` // Stored encrypted
	AsymmetricPublicKey  string        `gorm:"not null"          json:"asymmetric_public_key"`
	SymmetricKey         string        `gorm:"not null"          json:"symmetric_key"` // Stored encrypted
	AttachmentID         *uuid.UUID    `                         json:"attachment_id"`
	Attachment           Attachment    `                         json:"attachment"`
	MessageExpiryDefault MessageExpiry `gorm:"default:no_expiry" json:"-" sql:"type:ENUM(
        'fifteen_min',
        'thirty_min',
        'one_hour',
        'three_hour',
        'six_hour',
        'twelve_hour',
        'one_day',
        'three_day'
    )"` // Stored encrypted
}
