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

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

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

-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_creator(cake@internal@read_query:select()) -> cake@internal@read_query:select().
join_creator(In) ->
    Join = cake@join:inner(
        cake@join:table(<<"users"/utf8>>),
        begin
            _pipe = cake@where:col(<<"versions"/utf8, ".creator_id"/utf8>>),
            cake@where:eq(_pipe, cake@where:col(<<"creator"/utf8, ".id"/utf8>>))
        end,
        <<"creator"/utf8>>
    ),
    _pipe@1 = In,
    cake@select:join(_pipe@1, Join).

-spec join_published(cake@internal@read_query:select()) -> cake@internal@read_query:select().
join_published(In) ->
    Join = cake@join:inner(
        cake@join:table(<<"published"/utf8>>),
        begin
            _pipe = cake@where:col(<<"versions"/utf8, ".published_id"/utf8>>),
            cake@where:eq(
                _pipe,
                cake@where:col(<<"published"/utf8, ".id"/utf8>>)
            )
        end,
        <<"published"/utf8>>
    ),
    _pipe@1 = In,
    cake@select:join(_pipe@1, Join).

-spec where_variants(integer()) -> fun((cake@internal@read_query:select()) -> cake@internal@read_query:select()).
where_variants(Published_id) ->
    fun(In) -> _pipe = cake@where:col(<<"published"/utf8, ".id"/utf8>>),
        _pipe@1 = cake@where:eq(_pipe, cake@where:int(Published_id)),
        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(<<"versions"/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(),
    fun((cake@internal@read_query:select()) -> cake@internal@read_query:select())
) -> {ok, list({templates@template:template(), binary()})} |
    {error, sqlight:error()}.
select(Conn, Page, Where) ->
    Fields = [cake@select:col(<<"templates"/utf8, ".title"/utf8>>),
        cake@select:col(<<"templates"/utf8, ".description"/utf8>>),
        cake@select:col(<<"published"/utf8, ".id"/utf8>>),
        cake@select:col(<<"versions"/utf8, ".id"/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>>),
        cake@select:col(<<"creator"/utf8, ".username"/utf8>>)],
    Shape = fun(V) ->
        gleam@result:'try'(
            templates@template:decoder(V),
            fun(Template) ->
                gleam@result:'try'(
                    (gleam@dynamic:element(9, fun gleam@dynamic:string/1))(V),
                    fun(Creator) -> _pipe = {Template, Creator},
                        {ok, _pipe} end
                )
            end
        )
    end,
    gleam@dynamic:tuple2(
        fun templates@template:decoder/1,
        fun gleam@dynamic:string/1
    ),
    Query = begin
        _pipe@1 = cake@select:new(),
        _pipe@2 = cake@select:selects(_pipe@1, Fields),
        _pipe@3 = cake@select:from_table(_pipe@2, <<"versions"/utf8>>),
        _pipe@4 = join_published(_pipe@3),
        _pipe@5 = join_templates(_pipe@4),
        _pipe@6 = join_users(_pipe@5),
        _pipe@7 = join_creator(_pipe@6),
        _pipe@8 = Where(_pipe@7),
        _pipe@9 = cake@select:order_by(
            _pipe@8,
            <<"templates"/utf8, ".date"/utf8>>,
            desc
        ),
        _pipe@10 = cake@select:limit(_pipe@9, 30),
        _pipe@11 = cake@select:offset(_pipe@10, 30 * (Page - 1)),
        cake@select:to_query(_pipe@11)
    end,
    _pipe@12 = Conn,
    db@db:select(_pipe@12, Query, Shape).

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

-spec search_condition(binary()) -> cake@internal@read_query:where().
search_condition(Search) ->
    _pipe@2 = [begin
            _pipe = cake@where:col(<<"templates"/utf8, ".title"/utf8>>),
            cake@where:like(
                _pipe,
                <<<<"%"/utf8, Search/binary>>/binary, "%"/utf8>>
            )
        end,
        begin
            _pipe@1 = cake@where:col(<<"templates"/utf8, ".description"/utf8>>),
            cake@where:like(
                _pipe@1,
                <<<<"%"/utf8, Search/binary>>/binary, "%"/utf8>>
            )
        end],
    cake@where:'or'(_pipe@2).

-spec language_condition(binary()) -> cake@internal@read_query:where().
language_condition(Language) ->
    _pipe = cake@where:col(<<"templates"/utf8, ".language"/utf8>>),
    cake@where:eq(_pipe, cake@where:string(Language)).

-spec where_browse(binary(), binary()) -> fun((cake@internal@read_query:select()) -> cake@internal@read_query:select()).
where_browse(Language, Search) ->
    Condition = case {begin
            _pipe = Language,
            gleam@io:debug(_pipe)
        end,
        begin
            _pipe@1 = Search,
            gleam@io:debug(_pipe@1)
        end} of
        {<<"all"/utf8>>, <<""/utf8>>} ->
            none;

        {_, <<""/utf8>>} ->
            {some, language_condition(Language)};

        {<<"all"/utf8>>, _} ->
            {some, search_condition(Search)};

        {_, _} ->
            {some,
                begin
                    _pipe@2 = [language_condition(Language),
                        search_condition(Search)],
                    cake@where:'and'(_pipe@2)
                end}
    end,
    case Condition of
        none ->
            fun(In) -> In end;

        {some, C} ->
            fun(In@1) -> _pipe@3 = In@1,
                cake@select:where(_pipe@3, C) end
    end.
