package models

import (
	"context"
	"database/sql"
	"fmt"
	"time"

	"github.com/google/uuid"
	"github.com/uptrace/bun"
)

type UserAttributes struct {
	Groups []Group `json:"groups"`
}

type User struct {
	bun.BaseModel `bun:"table:users"`

	UserID     uuid.UUID      `bun:"type:uuid,pk,default:gen_random_uuid()" json:"userId"`
	FirstName  string         `bun:"firstname,notnull" json:"firstname"`
	LastName   string         `bun:"lastname,notnull" json:"lastname"`
	Email      string         `bun:"email,unique,notnull" json:"email"`
	Password   string         `bun:"password,notnull" json:"password,omitempty"`
	Phone      string         `bun:"phone,notnull" json:"phone"`
	CreatedAt  time.Time      `bun:"created_at,default:current_timestamp" json:"createdAt"`
	UpdatedAt  time.Time      `bun:"updated_at,default:current_timestamp" json:"updatedAt"`
	Events     []Event        `bun:"m2m:events_to_users,join:User=Event" json:"events,omitempty"`
	Articles   []*Blog        `bun:"rel:has-many,join:user_id=blog_id" json:"articles,omitempty"`
	Attributes UserAttributes `bun:"attributes,type:jsonb" json:"attributes"`
	Roles      []Role         `bun:"m2m:users_to_roles,join:User=Role" json:"roles,omitempty"`
}

func (u *User) Insert(db *bun.DB, ctx context.Context) (sql.Result, error) {
	return db.NewInsert().
		Model(u).
		Value("password", "crypt(?, gen_salt('bf'))", u.Password).
		Ignore().
		// Returning("user_id").
		Exec(ctx)
}

func Verify(db *bun.DB, ctx context.Context, email, password string) (*User, error) {
	var user User
	count, err := db.NewSelect().
		Model(&user).
		Where("email = ? AND password = crypt(?, password)", email, password).
		Limit(1).
		ScanAndCount(context.Background())
	if count == 0 {
		return nil, fmt.Errorf("invalid email or password")
	}
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, fmt.Errorf("invalid email or password")
		}
		return nil, err
	}

	return &user, nil
}
