defmodule DaProductApp.TerminalManagement.ParameterPushService do @moduledoc """ Service module for pushing terminal parameters via MQTT. Extends the existing OTA service with additional parameter push capabilities. """ require Logger alias DaProductApp.TerminalManagement alias DaProductApp.TerminalManagement.OtaService @doc """ Sends complete terminal parameters to a device including all configuration fields. """ def send_terminal_parameters(device_serial, parameters) do with {:ok, validated_params} <- validate_parameters(parameters), {:ok, config_attrs} <- build_ota_config_attrs(device_serial, validated_params) do case TerminalManagement.create_ota_configuration(config_attrs) do {:ok, config} -> OtaService.send_ota_configuration(config) {:error, changeset} -> Logger.error("Failed to create OTA configuration for #{device_serial}: #{inspect(changeset.errors)}") {:error, "Failed to create parameter configuration"} end else {:error, reason} -> Logger.error("Parameter validation failed for #{device_serial}: #{reason}") {:error, reason} end end @doc """ Sends a quick merchant configuration update with minimal required parameters. """ def send_quick_merchant_config(device_serial, merchant_id, terminal_id, opts \\ %{}) do base_params = %{ "merchant_id" => merchant_id, "terminal_id" => terminal_id, "mqtt_ip" => opts["mqtt_ip"] || "testapp.ariticapp.com", "mqtt_port" => opts["mqtt_port"] || 1883, "http_ip" => opts["http_ip"] || "demo.ctrmv.com", "http_port" => opts["http_port"] || 4001, "product_key" => opts["product_key"] || "pFppbioOCKlo5c8E", "product_secret" => opts["product_secret"] || "sj2AJl102397fQAV", "username" => opts["username"] || "user001", "keepalive_time" => opts["keepalive_time"] || 300, "heartbeat_interval" => opts["heartbeat_interval"] || 300, "play_language" => opts["play_language"] || 1 } send_terminal_parameters(device_serial, base_params) end @doc """ Sends a complete parameter set with all available configuration options. """ def send_full_parameters(device_serial, params) do complete_params = build_complete_parameter_set(device_serial, params) send_terminal_parameters(device_serial, complete_params) end defp validate_parameters(params) do required_fields = ["merchant_id", "terminal_id"] case Enum.find(required_fields, fn field -> is_nil(params[field]) or params[field] == "" end) do nil -> {:ok, params} missing_field -> {:error, "Missing required parameter: #{missing_field}"} end end defp build_ota_config_attrs(device_serial, params) do request_id = System.unique_integer([:positive]) product_key = params["product_key"] || "pFppbioOCKlo5c8E" attrs = %{ request_id: request_id, device_serial: device_serial, merchant_config: true, merchant_id: params["merchant_id"], terminal_id: params["terminal_id"], mqtt_ip: params["mqtt_ip"] || "testapp.ariticapp.com", mqtt_port: parse_integer(params["mqtt_port"], 1883), http_ip: params["http_ip"] || "demo.ctrmv.com", http_port: parse_integer(params["http_port"], 4001), product_key: product_key, product_secret: params["product_secret"] || "sj2AJl102397fQAV", client_id: params["client_id"] || device_serial, username: params["username"] || "user001", mqtt_topic: params["mqtt_topic"] || "/ota/#{product_key}/#{device_serial}/update", keepalive_time: parse_integer(params["keepalive_time"], 300), play_language: parse_integer(params["play_language"], 1), heartbeat_interval: parse_integer(params["heartbeat_interval"], 300) } {:ok, attrs} end defp build_complete_parameter_set(device_serial, params) do product_key = params["product_key"] || "pFppbioOCKlo5c8E" %{ "request_id" => System.unique_integer([:positive]), "merchant_config" => true, "merchant_id" => params["merchant_id"], "terminal_id" => params["terminal_id"], "mqtt_ip" => params["mqtt_ip"] || "testapp.ariticapp.com", "mqtt_port" => params["mqtt_port"] || 1883, "http_ip" => params["http_ip"] || "demo.ctrmv.com", "http_port" => params["http_port"] || 4001, "product_key" => product_key, "product_secret" => params["product_secret"] || "sj2AJl102397fQAV", "client_id" => params["client_id"] || device_serial, "username" => params["username"] || "user001", "mqtt_topic" => params["mqtt_topic"] || "/ota/#{product_key}/#{device_serial}/update", "keepalive_time" => params["keepalive_time"] || 300, "play_language" => params["play_language"] || -1, "heartbeat_interval" => params["heartbeat_interval"] || 300 } end defp parse_integer(value, default) when is_binary(value) do case Integer.parse(value) do {int, _} -> int :error -> default end end defp parse_integer(value, _default) when is_integer(value), do: value defp parse_integer(_value, default), do: default @doc """ Batch sends parameters to multiple devices. """ def batch_send_parameters(device_serials, parameters) when is_list(device_serials) do results = Enum.map(device_serials, fn device_serial -> case send_terminal_parameters(device_serial, parameters) do {:ok, message} -> {device_serial, :ok, message} {:error, reason} -> {device_serial, :error, reason} end end) successes = Enum.count(results, fn {_, status, _} -> status == :ok end) failures = Enum.count(results, fn {_, status, _} -> status == :error end) Logger.info("Batch parameter push completed: #{successes} successful, #{failures} failed") {:ok, %{ total: length(device_serials), successes: successes, failures: failures, results: results }} end end