-module(db@draft).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).

-export([add/2, where_mine/1, get/3]).
-export_type([get_err/0]).

-type get_err() :: {get_db_err, binary()}.

-spec draft_decoder() -> fun((gleam@dynamic:dynamic_()) -> {ok, integer()} |
    {error, list(gleam@dynamic:decode_error())}).
draft_decoder() ->
    gleam@dynamic:decode1(
        fun(Template_id) -> Template_id end,
        gleam@dynamic:field(<<"template_id"/utf8>>, fun gleam@dynamic:int/1)
    ).

-spec insert(sqlight:connection(), integer()) -> {ok, nil} |
    {error, sqlight:error()}.
insert(Conn, Template_id) ->
    Row = [cake@insert:int(Template_id)],
    Fields = [<<"template_id"/utf8>>],
    Query = begin
        _pipe@1 = cake@insert:from_values(
            <<"drafts"/utf8>>,
            Fields,
            [begin
                    _pipe = Row,
                    cake@insert:row(_pipe)
                end]
        ),
        cake@insert:to_query(_pipe@1)
    end,
    _pipe@2 = Conn,
    db@db:insert(_pipe@2, Query, draft_decoder()).

-spec add(sqlight:connection(), integer()) -> {ok, integer()} |
    {error, db@template:add_err()}.
add(Conn, Template_id) ->
    gleam@result:'try'(
        begin
            _pipe = Conn,
            _pipe@1 = insert(_pipe, Template_id),
            gleam@result:map_error(
                _pipe@1,
                fun(E) -> {add_db_err, erlang:element(3, E)} end
            )
        end,
        fun(_use0) ->
            nil = _use0,
            _pipe@2 = Conn,
            _pipe@3 = db@db:select_last_id(_pipe@2, <<"drafts"/utf8>>),
            gleam@result:map_error(
                _pipe@3,
                fun(_) ->
                    {add_db_err, <<"new draft id-select failed"/utf8>>}
                end
            )
        end
    ).

-spec where_mine(binary()) -> fun((cake@internal@read_query:select()) -> cake@internal@read_query:select()).
where_mine(Username) ->
    fun(In) -> _pipe = cake@where:col(<<"users"/utf8, ".username"/utf8>>),
        _pipe@1 = cake@where:eq(_pipe, cake@where:string(Username)),
        cake@select:where(In, _pipe@1) end.

-spec join_templates(cake@internal@read_query:select()) -> cake@internal@read_query:select().
join_templates(In) ->
    Join = cake@join:inner(
        cake@join:table(<<"templates"/utf8>>),
        begin
            _pipe = cake@where:col(<<"drafts"/utf8, ".template_id"/utf8>>),
            cake@where:eq(
                _pipe,
                cake@where:col(<<"templates"/utf8, ".id"/utf8>>)
            )
        end,
        <<"templates"/utf8>>
    ),
    _pipe@1 = In,
    cake@select:join(_pipe@1, Join).

-spec join_users(cake@internal@read_query:select()) -> cake@internal@read_query:select().
join_users(In) ->
    Join = cake@join:inner(
        cake@join:table(<<"users"/utf8>>),
        begin
            _pipe = cake@where:col(<<"templates"/utf8, ".user_id"/utf8>>),
            cake@where:eq(_pipe, cake@where:col(<<"users"/utf8, ".id"/utf8>>))
        end,
        <<"users"/utf8>>
    ),
    _pipe@1 = In,
    cake@select:join(_pipe@1, Join).

-spec select(sqlight:connection(), integer(), binary()) -> {ok,
        list(templates@template:template())} |
    {error, sqlight:error()}.
select(Conn, Page, Username) ->
    Fields = [cake@select:col(<<"templates"/utf8, ".title"/utf8>>),
        cake@select:col(<<"templates"/utf8, ".description"/utf8>>),
        cake@select:col(<<"templates"/utf8, ".args"/utf8>>),
        cake@select:col(<<"templates"/utf8, ".language"/utf8>>),
        cake@select:col(<<"templates"/utf8, ".raw"/utf8>>),
        cake@select:col(<<"templates"/utf8, ".date"/utf8>>),
        cake@select:col(<<"users"/utf8, ".username"/utf8>>)],
    Shape = fun templates@template:draft_decoder/1,
    Query = begin
        _pipe = cake@select:new(),
        _pipe@1 = cake@select:selects(_pipe, Fields),
        _pipe@2 = cake@select:from_table(_pipe@1, <<"drafts"/utf8>>),
        _pipe@3 = join_templates(_pipe@2),
        _pipe@4 = join_users(_pipe@3),
        _pipe@5 = (where_mine(Username))(_pipe@4),
        _pipe@6 = cake@select:order_by(
            _pipe@5,
            <<"templates"/utf8, ".date"/utf8>>,
            desc
        ),
        _pipe@7 = cake@select:limit(_pipe@6, 30),
        _pipe@8 = cake@select:offset(_pipe@7, 30 * (Page - 1)),
        cake@select:to_query(_pipe@8)
    end,
    _pipe@9 = Conn,
    db@db:select(_pipe@9, Query, Shape).

-spec get(sqlight:connection(), integer(), binary()) -> {ok,
        list(templates@template:template())} |
    {error, get_err()}.
get(Conn, Page, Username) ->
    _pipe = Conn,
    _pipe@1 = select(_pipe, Page, Username),
    gleam@result:map_error(
        _pipe@1,
        fun(E) -> {get_db_err, erlang:element(3, E)} end
    ).
