defmodule ToweropsWeb.HealthController do
  @moduledoc false

  use ToweropsWeb, :controller

  alias Ecto.Adapters.SQL
  alias Towerops.Repo

  def index(conn, _params) do
    require Logger

    db_status = check_database()
    redis_status = check_redis()

    # Log health check results for debugging
    Logger.debug("Health check: db=#{inspect(db_status)}, redis=#{inspect(redis_status)}")

    all_healthy = db_status == :ok and redis_status in [:ok, :not_configured]

    if all_healthy do
      conn
      |> put_resp_content_type("application/json")
      |> send_resp(
        200,
        Jason.encode!(%{
          status: "ok",
          database: "connected",
          redis: redis_status_string(redis_status),
          version: :towerops |> Application.spec(:vsn) |> to_string()
        })
      )
    else
      conn
      |> put_resp_content_type("application/json")
      |> send_resp(
        503,
        Jason.encode!(%{
          status: "error",
          database: db_status_string(db_status),
          redis: redis_status_string(redis_status)
        })
      )
    end
  end

  defp check_database do
    case SQL.query(Repo, "SELECT 1", []) do
      {:ok, _} -> :ok
      {:error, _} -> :error
    end
  end

  defp check_redis do
    require Logger

    redis_config = Application.get_env(:towerops, :redis, [])

    if Keyword.has_key?(redis_config, :host) do
      # Redis is configured, check connectivity with short timeout for health check
      case Towerops.RedisHealthCheck.check_health(redis_config, 2_000) do
        :ok ->
          :ok

        {:error, reason} ->
          Logger.error("Redis health check failed: #{inspect(reason)}")
          :error
      end
    else
      # Redis not configured (e.g., in development without Redis)
      Logger.debug("Redis not configured")
      :not_configured
    end
  end

  defp db_status_string(:ok), do: "connected"
  defp db_status_string(:error), do: "disconnected"

  defp redis_status_string(:ok), do: "connected"
  defp redis_status_string(:error), do: "disconnected"
  defp redis_status_string(:not_configured), do: "not_configured"

  @doc """
  Time diagnostic endpoint for debugging TOTP issues.
  Returns server time from multiple sources.
  """
  def time(conn, _params) do
    system_time = System.system_time(:second)
    os_time = :os.system_time(:second)
    datetime_now = DateTime.utc_now()

    conn
    |> put_resp_content_type("application/json")
    |> send_resp(
      200,
      Jason.encode!(%{
        system_time: system_time,
        system_time_iso: system_time |> DateTime.from_unix!() |> DateTime.to_iso8601(),
        os_time: os_time,
        os_time_iso: os_time |> DateTime.from_unix!() |> DateTime.to_iso8601(),
        datetime_now: DateTime.to_unix(datetime_now),
        datetime_now_iso: DateTime.to_iso8601(datetime_now),
        time_sources_agree: system_time == os_time and system_time == DateTime.to_unix(datetime_now)
      })
    )
  end
end
