%%%-------------------------------------------------------------------
%%% @author aresei
%%% @copyright (C) 2023, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 16. 5月 2023 12:48
%%%-------------------------------------------------------------------
-module(device_bo).
-author("aresei").
-include("iot.hrl").

%% API
-export([get_all_devices/0, get_host_devices/1, get_device_by_uuid/1, change_status/2]).

-spec get_all_devices() -> {ok, Devices :: [map()]} | {error, Reason :: any()}.
get_all_devices() ->
    mysql_pool:get_all(mysql_iot, <<"SELECT * FROM device WHERE device_uuid != ''">>).

-spec get_host_devices(HostId :: integer()) -> {ok, Devices :: [binary()]} | {error, Reason::any()}.
get_host_devices(HostId) when is_integer(HostId) ->
    case mysql_pool:get_all(mysql_iot, <<"SELECT device_uuid FROM device WHERE host_id = ? AND device_uuid != ''">>, [HostId]) of
        {ok, Devices} ->
            {ok, lists:map(fun(#{<<"device_uuid">> := DeviceUUID}) -> DeviceUUID end, Devices)};
        {error, Reason} ->
            {error, Reason}
    end.

-spec get_device_by_uuid(DeviceUUID :: binary()) -> {ok, DeviceInfo :: map()} | undefined.
get_device_by_uuid(DeviceUUID) when is_binary(DeviceUUID) ->
    mysql_pool:get_row(mysql_iot, <<"SELECT * FROM device WHERE device_uuid = ? LIMIT 1">>, [DeviceUUID]).

%% 修改主机的状态
-spec change_status(DeviceUUID :: binary(), Status :: integer()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}.
change_status(DeviceUUID, NStatus) when is_binary(DeviceUUID), is_integer(NStatus) ->
    case change_status0(DeviceUUID, NStatus) of
        Result = {ok, _} ->
            event_logs_bo:insert(?EVENT_DEVICE, DeviceUUID, NStatus),
            Result;
        Error ->
            Error
    end.
change_status0(DeviceUUID, ?DEVICE_ONLINE) when is_binary(DeviceUUID) ->
    Timestamp = calendar:local_time(),
    case mysql_pool:get_row(mysql_iot, <<"SELECT status FROM device WHERE device_uuid = ? LIMIT 1">>, [DeviceUUID]) of
        {ok, #{<<"status">> := -1}} ->
            mysql_pool:update_by(mysql_iot, <<"UPDATE device SET status = ?, access_at = ?, updated_at = ? WHERE device_uuid = ? LIMIT 1">>, [?DEVICE_ONLINE, Timestamp, Timestamp, DeviceUUID]);
        {ok, _} ->
            mysql_pool:update_by(mysql_iot, <<"UPDATE device SET status = ?, updated_at = ? WHERE device_uuid = ? LIMIT 1">>, [?DEVICE_ONLINE, Timestamp, DeviceUUID]);
        undefined ->
            {error, <<"device not found">>}
    end;
change_status0(DeviceUUID, ?DEVICE_OFFLINE) when is_binary(DeviceUUID) ->
    mysql_pool:update_by(mysql_iot, <<"UPDATE device SET status = ? WHERE device_uuid = ? LIMIT 1">>, [?DEVICE_OFFLINE, DeviceUUID]).