-module(users@signin).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).

-export([get_user_from_db/2, sign_in/3]).
-export_type([sign_in_err/0]).

-type sign_in_err() :: invalid_username |
    invalid_password |
    {sign_in_failed, binary()}.

-spec add_session_key_to_db(sqlight:connection(), integer(), binary()) -> {ok,
        nil} |
    {error, sign_in_err()}.
add_session_key_to_db(Conn, User_id, Key) ->
    _pipe = Conn,
    _pipe@1 = db@session_key:add(_pipe, User_id, Key),
    gleam@result:map_error(
        _pipe@1,
        fun(E) ->
            {add_db_err, S} = E,
            {sign_in_failed, S}
        end
    ).

-spec get_user_from_db(sqlight:connection(), binary()) -> {ok,
        users@user:user()} |
    {error, sign_in_err()}.
get_user_from_db(Conn, Username) ->
    _pipe = Conn,
    _pipe@1 = db@user:get(_pipe, Username),
    gleam@result:map_error(_pipe@1, fun(E) -> case E of
                invalid_user ->
                    invalid_username;

                {get_db_err, S} ->
                    {sign_in_failed, S}
            end end).

-spec sign_in(sqlight:connection(), binary(), binary()) -> {ok, binary()} |
    {error, sign_in_err()}.
sign_in(Conn, Username, Password) ->
    gleam@result:'try'(
        begin
            _pipe = Conn,
            get_user_from_db(_pipe, Username)
        end,
        fun(U) ->
            gleam@bool:guard(
                users@user:check_password(Password, erlang:element(4, U)),
                {error, invalid_password},
                fun() ->
                    Key = users@session_key:generate(),
                    gleam@result:'try'(
                        begin
                            _pipe@1 = Conn,
                            add_session_key_to_db(
                                _pipe@1,
                                erlang:element(2, U),
                                Key
                            )
                        end,
                        fun(_use0) ->
                            nil = _use0,
                            _pipe@2 = Key,
                            {ok, _pipe@2}
                        end
                    )
                end
            )
        end
    ).
