----------------------------------------------------------------------------------------------------
-- Users, their statuses and groups
----------------------------------------------------------------------------------------------------

-- name: migration-0001-create-users#
CREATE TABLE IF NOT EXISTS groups (
   id INTEGER PRIMARY KEY AUTOINCREMENT
 , name TEXT
 , priority INTEGER CHECK(priority IS NOT NULL AND priority > 0)
);

INSERT OR IGNORE INTO groups (id, name, priority) VALUES (0, 'root', 20);
INSERT OR IGNORE INTO groups (id, name, priority) VALUES (1, 'users', 10);
INSERT OR IGNORE INTO groups (id, name, priority) VALUES (2, 'guests', 0);

CREATE TABLE IF NOT EXISTS user_statuses (
   id INTEGER PRIMARY KEY AUTOINCREMENT
 , name TEXT
 , UNIQUE(name)
);

INSERT OR IGNORE INTO user_statuses (id, name) VALUES (-4, 'passwdchng');
INSERT OR IGNORE INTO user_statuses (id, name) VALUES (-3, 'unverified');
INSERT OR IGNORE INTO user_statuses (id, name) VALUES (-2, 'unapproved');
INSERT OR IGNORE INTO user_statuses (id, name) VALUES (-1, 'disabled');
INSERT OR IGNORE INTO user_statuses (id, name) VALUES (1, 'enabled');

CREATE TABLE IF NOT EXISTS users (
   id INTEGER PRIMARY KEY AUTOINCREMENT
 , group_id INTEGER
 , name TEXT
 , email TEXT
 , hash TEXT
 , status_id INTEGER
 , created_at TEXT DEFAULT (datetime('now'))
 , verification_token TEXT DEFAULT (lower(hex(randomblob(32))))
 , verified_at TEXT
 , approved_at TEXT
 , enabled_at TEXT
 , FOREIGN KEY(group_id) REFERENCES groups(id)
 , FOREIGN KEY(status_id) REFERENCES user_statuses(id)
 , UNIQUE(name)
 , UNIQUE(email)
);

-- name: try-create-user^
INSERT INTO users (
   name
 , email
 , hash
 , group_id
 , status_id
)
VALUES (:name, :email, :hash, :gid, :sid)
RETURNING *
;

-- name: fetch_user^
SELECT
   *
FROM users
WHERE
   id = :uid
;

-- name: list-users
SELECT
   *
FROM users
;

-- name: list-unverified-users
SELECT
   *
FROM users
WHERE
   status_id = -2
   AND verified_at IS NULL
;

-- name: try-verify-user^
UPDATE users
SET
   verified_at = datetime('now')
 , verification_token = lower(hex(randomblob(32)))
WHERE
   verification_token = :token
RETURNING
   id
 , name
;

-- name: enable-user^
UPDATE users
SET
   enabled_at = datetime('now')
WHERE
   id = :uid
RETURNING
   id
 , name
;

-- name: disable-user^
UPDATE users
SET
   enabled_at = NULL
WHERE
   id = :uid
RETURNING
   id
 , name
;

-- name: approve-user^
UPDATE users
SET
   approved_at = datetime('now')
WHERE
   id = :uid
RETURNING
   id
 , name
;

-- name: set-user-status^
UPDATE users
SET
   status_id = (SELECT id FROM user_statuses WHERE id = :status OR name = :status)
WHERE
   id = :uid
RETURNING
   id
 , name
;
