package database

import (
	"fmt"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

// GCC Toolchain for Windows: https://jmeubank.github.io/tdm-gcc/

func migrateInitial(orm *gorm.DB) {
	err := orm.AutoMigrate(&User{})
	if err != nil {
		fmt.Println(fmt.Errorf("failed to migrate User"))
	}
	err = orm.AutoMigrate(&Task{})
	if err != nil {
		fmt.Println(fmt.Errorf("failed to migrate Task"))
	}
}

func (db *Database) Initialize() {
	orm, err := gorm.Open(sqlite.Open(db.Location), &gorm.Config{})
	if err != nil {
		fmt.Println(fmt.Errorf("failed to connect Database"))
	}
	migrateInitial(orm)
	db.ORM = orm
}

func (db *Database) GetAllTasks(username string) []Task {
	var tasks []Task
	db.ORM.Where("username = ?", username).Find(&tasks)
	return tasks
}

func (db *Database) FilteredTasks(username string, filter string) []Task {
	var tasks []Task
	query := fmt.Sprintf("SELECT * FROM tasks WHERE username = '%s' AND description LIKE '%s'", username, filter)
	db.ORM.Raw(query).Scan(&tasks)
	return tasks
}

func (db *Database) CreateTask(username string, description string) Task {
	task := Task{
		ID:          0,
		Username:    username,
		Description: description,
		Done:        false,
	}
	db.ORM.Create(&task)
	return task
}

func (db *Database) DeleteTask(id string) bool {
	result := db.ORM.Delete(&Task{}, id)
	if result.RowsAffected == 0 {
		return false
	}
	return true
}

func (db *Database) UpdateTask(id string, done string) bool {
	task := Task{}
	db.ORM.First(&task, id)
	result := db.ORM.Model(&task).Update("done", done)
	if result.RowsAffected == 0 {
		return false
	}
	return true
}

func (db *Database) CreateUser(username string, password string) error {
	user := User{Username: username, Password: password, LoggedIn: true}
	result := db.ORM.Create(&user)
	return result.Error
}

func (db *Database) LoginUser(username string, password string) bool {
	user := User{Username: username, Password: password}
	result := db.ORM.Where("username = ? AND password = ?", username, password).Find(&user)
	if result.RowsAffected == 1 {
		db.ORM.Model(&user).Update("logged_in", true)
		return true
	}
	return false
}

func (db *Database) LogoutUser(username string) bool {
	user := User{Username: username}
	result := db.ORM.Where("username = ? and logged_in = ?", username, true).Find(&user)
	if result.RowsAffected == 1 {
		db.ORM.Model(&user).Update("logged_in", false)
		return true
	}
	return false
}

func (db *Database) UserIsLoggedIn(username string) bool {
	user := User{Username: username}
	result := db.ORM.Where("username = ? and logged_in = ?", username, true).Find(&user)
	if result.RowsAffected == 1 {
		return true
	}
	return false
}

func (db *Database) ChangeUserPassword(username string, password string) {
	user := User{Username: username}
	db.ORM.Where("username = ?", username).Find(&user)
	db.ORM.Model(&user).Update("password", password)
}
