# Firehose blog controller tests

defmodule FirehoseWeb.BlogTest do
  use FirehoseWeb.ConnCase

  defp visit_blog_page(conn, blog_id, suffix \\ "") do
    path = "/blog/#{blog_id}" <> suffix
    body = conn |> get(path) |> html_response(200)
    body
  end

  describe "engineering blog (HTML)" do
    test "GET /blog/engineering returns HTML index with layout", %{conn: conn} do
      body = visit_blog_page(conn, "engineering")
      assert body =~ "Engineering Blog"
      assert body =~ "firehose"
    end

    test "GET /blog/engineering/:slug returns HTML post with layout", %{conn: conn} do
      body = visit_blog_page(conn, "engineering", "/hello-world")
      assert body =~ "Hello World"
    end
  end

  describe "release notes blog (HTML)" do
    test "GET /blog/releases returns HTML index", %{conn: conn} do
      body = visit_blog_page(conn, "releases")
      assert body =~ "Release Notes"
      assert body =~ "v0.1.0 Released"
    end

    test "GET /blog/releases/:slug returns HTML post", %{conn: conn} do
      body = visit_blog_page(conn, "releases", "/v0-1-0")
      assert body =~ "v0.1.0 Released"
    end
  end

  describe "input validation" do
    test "GET /blog/nonexistent returns 404", %{conn: conn} do
      assert conn |> get("/blog/nonexistent") |> html_response(404)
    end

    test "GET /blog/engineering?page=abc falls back to page 1", %{conn: conn} do
      assert conn |> get("/blog/engineering?page=abc") |> html_response(200) =~ "Engineering Blog"
    end

    test "GET /blog/engineering?page=-1 falls back to page 1", %{conn: conn} do
      assert conn |> get("/blog/engineering?page=-1") |> html_response(200) =~ "Engineering Blog"
    end

    test "GET /blog/engineering?page=0 falls back to page 1", %{conn: conn} do
      assert conn |> get("/blog/engineering?page=0") |> html_response(200) =~ "Engineering Blog"
    end

    test "GET /blog/engineering/nonexistent-post returns 404", %{conn: conn} do
      assert_raise Blogex.NotFoundError, fn ->
        get(conn, "/blog/engineering/nonexistent-post")
      end
    end
  end

  describe "engineering blog (JSON API)" do
    test "GET /api/blog/engineering returns post index", %{conn: conn} do
      assert %{"blog" => "engineering", "posts" => posts} =
               conn
               |> put_req_header("accept", "application/json")
               |> get("/api/blog/engineering")
               |> json_response(200)

      assert is_list(posts)
      refute Enum.empty?(posts)
    end

    test "GET /api/blog/engineering/:slug returns a post", %{conn: conn} do
      assert %{"id" => "hello-world", "title" => "Hello World"} =
               conn
               |> put_req_header("accept", "application/json")
               |> get("/api/blog/engineering/hello-world")
               |> json_response(200)
    end

    test "GET /api/blog/engineering/:slug returns 404 for missing post", %{conn: conn} do
      assert conn
             |> put_req_header("accept", "application/json")
             |> get("/api/blog/engineering/nonexistent")
             |> response(404)
    end

    test "GET /api/blog/engineering/feed.xml returns RSS", %{conn: conn} do
      response = conn |> get("/api/blog/engineering/feed.xml")
      assert response(response, 200) =~ "<rss"
      assert response_content_type(response, :xml)
    end

    test "GET /api/blog/engineering/tag/:tag returns JSON with posts", %{conn: conn} do
      assert %{"blog" => "engineering", "tag" => "elixir", "posts" => posts} =
               conn
               |> put_req_header("accept", "application/json")
               |> get("/api/blog/engineering/tag/elixir")
               |> json_response(200)

      assert is_list(posts)
    end
  end

  describe "release notes blog (JSON API)" do
    test "GET /api/blog/releases returns post index", %{conn: conn} do
      assert %{"blog" => "release_notes", "posts" => posts} =
               conn
               |> put_req_header("accept", "application/json")
               |> get("/api/blog/releases")
               |> json_response(200)

      assert is_list(posts)
      refute Enum.empty?(posts)
    end

    test "GET /api/blog/releases/:slug returns a post", %{conn: conn} do
      assert %{"id" => "v0-1-0", "title" => "v0.1.0 Released"} =
               conn
               |> put_req_header("accept", "application/json")
               |> get("/api/blog/releases/v0-1-0")
               |> json_response(200)
    end

    test "GET /api/blog/releases/feed.xml returns RSS", %{conn: conn} do
      response = conn |> get("/api/blog/releases/feed.xml")
      assert response(response, 200) =~ "<rss"
      assert response_content_type(response, :xml)
    end

    test "GET /api/blog/releases/tag/:tag returns JSON with posts", %{conn: conn} do
      assert %{"blog" => "release_notes", "tag" => "elixir", "posts" => posts} =
               conn
               |> put_req_header("accept", "application/json")
               |> get("/api/blog/releases/tag/elixir")
               |> json_response(200)

      assert is_list(posts)
    end
  end
end
