package models

import (
	"fmt"
	"strconv"
	"time"

	"github.com/sujit-baniya/fiber-boilerplate/config"

	"github.com/sujit-baniya/fiber-boilerplate/app"
	"gorm.io/gorm"
)

type User struct {
	ID            uint `gorm:"primarykey"`
	CreatedAt     time.Time
	UpdatedAt     time.Time
	DeletedAt     gorm.DeletedAt `gorm:"index"`
	FirstName     string         `json:"first_name" gorm:"first_name"` //nolint:gofmt
	LastName      string         `json:"last_name" gorm:"last_name"`   //nolint:gofmt
	Email         string         `json:"email" gorm:"email"`
	Password      string         `json:"-" gorm:"password"`
	EmailVerified bool           `json:"email_verified" gorm:"email_verified"`
	IsAdmin       bool           `json:"is_admin" gorm:"is_admin"`
	Balance       float32        `json:"balance" gorm:"balance"`
	UserSetting   UserSetting    `json:"user_setting" gorm:"-"`
	RoleID        uint           `json:"role_id" gorm:"role_id"`
	Role          Roles          `gorm:"foreignKey:RoleID"` // Establecer relación con Roles

}

type Role struct {
	ID          uint   `gorm:"primarykey"`
	Name        string `json:"name" gorm:"name"`               //nolint:gofmt
	Description string `json:"description" gorm:"description"` //nolint:gofmt
	CreatedAt   time.Time
	UpdatedAt   time.Time
	DeletedAt   gorm.DeletedAt `gorm:"index"`
}

func GetUserByEmail(email string) (*Users, error) {
	var user Users
	if err := app.Http.Database.Where(&Users{Email: email}).First(&user).Error; err != nil {
		return nil, err
	}
	return &user, nil //nolint:wsl
}

func GetVerifiedUserByEmail(usuario string) (*Users, error) {
	var user Users
	if err := app.Http.Database.Where(&Users{NombreUsuario: usuario}).First(&user).Error; err != nil {
		return nil, err
	}
	return &user, nil //nolint:wsl
}

func GetUserById(id interface{}) (*Users, error) {
	var user Users
	if err := app.Http.Database.Where("id = ? ", id).First(&user).Error; err != nil {
		return nil, err
	}

	return &user, nil
}

func (u *User) Update() error {
	if u.ID != 0 {
		if err := app.Http.Database.Updates(&u).Error; err != nil {
			return err
		}
	} else {
		if err := app.Http.Database.Where(&User{Email: u.Email}).Updates(&u).Error; err != nil {
			return err
		}
	}
	app.Http.Database.First(&u)
	u.Settings()
	return nil
}

func (u *User) AddAmount(amount string, AlreadyAdded bool) {
	if AlreadyAdded {
		return
	}
	value, err := strconv.ParseFloat(amount, 32)
	if err != nil {
		// do something sensible
	}
	u.Balance += float32(value)
	app.Http.Database.Updates(&u)
}

func (u *User) Settings() (UserSetting, error) {
	userSettings := UserSetting{UserID: u.ID}
	err := userSettings.Get()
	if err != nil {
		return UserSetting{}, err
	}
	u.UserSetting = userSettings
	return userSettings, nil
}

func (u *User) Can(permission string) bool {
	return app.Http.Auth.Casbin.Can(fmt.Sprintf("%d", u.ID), permission, config.MatchAll)
}
