package invites

import (
	"database/sql"
	"errors"
	"time"

	"git.tilde.town/tildetown/town/codes"
	_ "github.com/mattn/go-sqlite3"
)

const (
	dsn = "/town/var/invites/invites.db?mode=rw"
)

type Invite struct {
	ID      int64
	Created time.Time
	Code    string
	Email   string
	Used    bool
}

func (i *Invite) Insert(db *sql.DB) error {
	stmt, err := db.Prepare(`
		INSERT INTO invites (code, email) VALUES (?, ?)
	`)
	if err != nil {
		return err
	}

	i.Code = codes.NewCode(i.Email)

	_, err = stmt.Exec(i.Code, i.Email)
	if err != nil {
		return err
	}
	defer stmt.Close()

	return nil
}

func ConnectDB() (*sql.DB, error) {
	db, err := sql.Open("sqlite3", dsn)
	if err != nil {
		return nil, err
	}

	return db, nil
}

func Get(db *sql.DB, code string) (*Invite, error) {
	inv := &Invite{
		Code: code,
	}
	var created string
	var used int
	stmt, err := db.Prepare(`
		SELECT id, created, email, used
		FROM invites WHERE code = ?`)
	if err != nil {
		return nil, err
	}

	row := stmt.QueryRow(code)
	if err != nil {
		return nil, err
	}
	defer stmt.Close()

	err = row.Scan(
		&inv.ID,
		&created,
		&inv.Email,
		&used,
	)
	if err != nil {
		return nil, err
	}

	inv.Created, err = time.Parse("2006-01-02T15:04", created)
	if err != nil {
		return inv, err
	}

	inv.Used = used > 0

	return inv, nil
}

func (i *Invite) MarkUsed(db *sql.DB) (err error) {
	var stmt *sql.Stmt
	var result sql.Result
	var rowsAffected int64
	if stmt, err = db.Prepare(`UPDATE invites SET used = 1 WHERE id = ?`); err != nil {
		return
	}

	if result, err = stmt.Exec(i.ID); err != nil {
		return
	}

	if rowsAffected, err = result.RowsAffected(); err != nil {
		return
	}

	if rowsAffected == 0 {
		err = errors.New("no rows affected")
	}

	return
}
