defmodule ToweropsWeb.Plugs.MobileAuthTest do
  use ToweropsWeb.ConnCase, async: true

  import Towerops.AccountsFixtures

  alias Towerops.MobileSessions
  alias ToweropsWeb.Plugs.MobileAuth

  describe "init/1" do
    test "returns options unchanged" do
      opts = [some: :option]
      assert MobileAuth.init(opts) == opts
    end

    test "returns empty list unchanged" do
      assert MobileAuth.init([]) == []
    end
  end

  describe "call/2 with valid authorization" do
    setup do
      user = user_fixture()

      {:ok, session} =
        MobileSessions.create_mobile_session(%{
          user_id: user.id,
          device_name: "Test iPhone"
        })

      %{user: user, session: session}
    end

    test "authenticates successfully with valid Bearer token", %{
      conn: conn,
      user: user,
      session: session
    } do
      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> put_req_header("authorization", "Bearer #{session.token}")
        |> MobileAuth.call([])

      refute conn.halted
      assert conn.assigns.current_user.id == user.id
      assert conn.assigns.current_mobile_session.id == session.id
    end
  end

  describe "call/2 with missing authorization" do
    test "returns 401 when Authorization header is missing", %{conn: conn} do
      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> MobileAuth.call([])

      assert conn.halted
      assert conn.status == 401

      assert json_response(conn, 401) == %{
               "error" => "Authorization header is missing or invalid"
             }
    end
  end

  describe "call/2 with invalid token" do
    test "returns 401 for non-existent token", %{conn: conn} do
      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> put_req_header("authorization", "Bearer invalid-token-xxx")
        |> MobileAuth.call([])

      assert conn.halted
      assert conn.status == 401

      assert json_response(conn, 401) == %{
               "error" => "Invalid or expired authentication token"
             }
    end
  end

  describe "call/2 with expired session" do
    setup do
      user = user_fixture()
      expires_at = DateTime.add(DateTime.utc_now(), -1, :day)

      {:ok, session} =
        MobileSessions.create_mobile_session(%{
          user_id: user.id,
          device_name: "Expired iPhone",
          expires_at: expires_at
        })

      %{user: user, session: session}
    end

    test "returns 401 for expired session token", %{conn: conn, session: session} do
      conn =
        conn
        |> put_req_header("content-type", "application/json")
        |> put_req_header("authorization", "Bearer #{session.token}")
        |> MobileAuth.call([])

      assert conn.halted
      assert conn.status == 401

      assert json_response(conn, 401) == %{
               "error" => "Invalid or expired authentication token"
             }
    end
  end
end
