%%%-------------------------------------------------------------------
%%% @doc Mnesia bootstrap and runtime startup helpers.
%%%
%%% `init/0` is a manual, one-time bootstrap operation. Application
%%% startup must call `start/0`, which only starts an existing schema and
%%% verifies required tables.
%%%-------------------------------------------------------------------
-module(iot_mnesia).

-include("iot_tables.hrl").

-export([safe_start/0, stop/0]).

-define(TABLES, [efka_client]).
-define(WAIT_TIMEOUT, 5000).

safe_start() ->
    case ensure_schema() of
        create_and_start ->
            ok = mnesia:start(),
            ok = create_tables(),
            ok = wait_for_tables();
        only_start ->
            ok = mnesia:start(),
            ok = wait_for_tables()
    end,
    log_runtime_info().

ensure_schema() ->
    stopped = mnesia:stop(),
    case mnesia:create_schema([node()]) of
        ok ->
            create_and_start;
        {error, {_, {already_exists, _}}} ->
            only_start;
        {error, {_, already_exists}} ->
            only_start;
        {error, _Reason} ->
            only_start
    end.

-spec stop() -> ok.
stop() ->
    _ = mnesia:stop(),
    ok.

-spec create_tables() -> ok.
create_tables() ->
    case efka_client_store:ensure_table() of
        ok ->
            ok;
        {error, Reason} ->
            {error, {create_table_failed, {efka_client, Reason}}}
    end.

-spec wait_for_tables() -> ok.
wait_for_tables() ->
    case mnesia:wait_for_tables(?TABLES, ?WAIT_TIMEOUT) of
        ok ->
            ok;
        {timeout, Tables} ->
            {error, {mnesia_tables_timeout, Tables}};
        {error, Reason} ->
            {error, {mnesia_tables_error, Reason}}
    end.

-spec log_runtime_info() -> ok.
log_runtime_info() ->
    logger:debug("[iot_mnesia] node: ~p, dir: ~p, tables: ~p", [
        node(),
        mnesia:system_info(directory),
        mnesia:system_info(tables)
    ]),
    ok.