defmodule MicrowavepropWeb.RoverLocationsLiveTest do
  use MicrowavepropWeb.ConnCase, async: true

  import Phoenix.LiveViewTest

  alias Microwaveprop.Rover
  alias Microwaveprop.Rover.Location

  describe "anonymous visitor" do
    test "can view the locations page", %{conn: conn} do
      {:ok, _lv, html} = live(conn, ~p"/rover-locations")
      assert html =~ "Rover Locations"
      assert html =~ "Sign in"
    end

    test "shows existing locations from any user", %{conn: conn} do
      user = Microwaveprop.AccountsFixtures.user_fixture()

      {:ok, _} =
        Rover.create_location(user, %{
          lat: 32.5,
          lon: -97.5,
          status: :good,
          notes: "great hill"
        })

      {:ok, _lv, html} = live(conn, ~p"/rover-locations")
      assert html =~ "Good"
      assert html =~ "great hill"
    end

    test "Add button is disabled for anonymous users", %{conn: conn} do
      {:ok, _lv, html} = live(conn, ~p"/rover-locations")
      assert html =~ ~s(disabled)
      assert html =~ "Add location"
    end

    test "status filter narrows the visible rows", %{conn: conn} do
      user = Microwaveprop.AccountsFixtures.user_fixture()
      {:ok, _} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good, notes: "ideal-spot"})
      {:ok, _} = Rover.create_location(user, %{lat: 33.0, lon: -98.0, status: :bad, notes: "no-go-spot"})

      {:ok, lv, html} = live(conn, ~p"/rover-locations")
      assert html =~ "ideal-spot"
      assert html =~ "no-go-spot"

      html =
        lv
        |> form("form[phx-change=filter_status]", %{"value" => "good"})
        |> render_change()

      assert html =~ "ideal-spot"
      refute html =~ "no-go-spot"

      html =
        lv
        |> form("form[phx-change=filter_status]", %{"value" => "bad"})
        |> render_change()

      refute html =~ "ideal-spot"
      assert html =~ "no-go-spot"
    end
  end

  describe "logged-in user" do
    setup :register_and_log_in_user

    test "can add a new location", %{conn: conn} do
      {:ok, lv, _html} = live(conn, ~p"/rover-locations")

      lv |> element("button", "Add location") |> render_click()

      lv
      |> form("#location-form",
        location: %{lat: "32.5", lon: "-97.5", status: "good", notes: "test note"}
      )
      |> render_submit()

      html = render(lv)
      assert html =~ "test note"
    end

    test "typing a grid populates lat/lon", %{conn: conn} do
      {:ok, lv, _html} = live(conn, ~p"/rover-locations")
      lv |> element("button", "Add location") |> render_click()

      html =
        lv
        |> form("#location-form",
          location: %{
            grid: "EM12kp",
            lat: "",
            lon: "",
            status: "good",
            notes: ""
          }
        )
        |> render_change(%{"_target" => ["location", "grid"]})

      # EM12kp center: lat 32.645833, lon -97.125
      assert html =~ ~s(value="32.645833")
      assert html =~ ~s(value="-97.125")
    end

    test "typing lat/lon populates the grid field", %{conn: conn} do
      {:ok, lv, _html} = live(conn, ~p"/rover-locations")
      lv |> element("button", "Add location") |> render_click()

      html =
        lv
        |> form("#location-form",
          location: %{
            grid: "",
            lat: "32.5",
            lon: "-97.5",
            status: "good",
            notes: ""
          }
        )
        |> render_change(%{"_target" => ["location", "lat"]})

      assert html =~ ~s(value="EM12gm")
    end

    test "the location cell links to the show page", %{conn: conn, user: user} do
      {:ok, loc} =
        Rover.create_location(user, %{
          lat: 32.5,
          lon: -97.5,
          status: :good,
          notes: "rooftop spot"
        })

      {:ok, lv, _html} = live(conn, ~p"/rover-locations")

      assert has_element?(lv, "a[href='/rover-locations/#{loc.id}']")
    end

    test "edit/delete buttons appear only on the owner's row", %{conn: conn, user: user} do
      other = Microwaveprop.AccountsFixtures.user_fixture()
      {:ok, mine} = Rover.create_location(user, %{lat: 32.0, lon: -97.0, status: :good})
      {:ok, theirs} = Rover.create_location(other, %{lat: 33.0, lon: -98.0, status: :bad})

      {:ok, lv, _html} = live(conn, ~p"/rover-locations")

      assert has_element?(lv, "button[phx-click=edit][phx-value-id='#{mine.id}']", "Edit")
      assert has_element?(lv, "button[phx-click=delete][phx-value-id='#{mine.id}']", "Delete")
      refute has_element?(lv, "button[phx-click=edit][phx-value-id='#{theirs.id}']", "Edit")
      refute has_element?(lv, "button[phx-click=delete][phx-value-id='#{theirs.id}']", "Delete")
    end
  end

  describe "admin" do
    test "sees edit/delete on every row and can delete a stranger's location", %{conn: conn} do
      admin = Microwaveprop.AccountsFixtures.user_fixture()
      {:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
      other = Microwaveprop.AccountsFixtures.user_fixture()

      {:ok, theirs} = Rover.create_location(other, %{lat: 33.0, lon: -98.0, status: :good})

      conn = log_in_user(conn, admin)
      {:ok, lv, _html} = live(conn, ~p"/rover-locations")

      assert has_element?(lv, "button[phx-click=edit][phx-value-id='#{theirs.id}']", "Edit")
      assert has_element?(lv, "button[phx-click=delete][phx-value-id='#{theirs.id}']", "Delete")

      lv
      |> element("button[phx-click=delete][phx-value-id='#{theirs.id}']")
      |> render_click()

      refute Microwaveprop.Repo.get(Location, theirs.id)
    end

    test "can edit a stranger's location", %{conn: conn} do
      admin = Microwaveprop.AccountsFixtures.user_fixture()
      {:ok, admin} = Microwaveprop.Accounts.admin_update_user(admin, %{is_admin: true})
      other = Microwaveprop.AccountsFixtures.user_fixture()

      {:ok, theirs} =
        Rover.create_location(other, %{
          lat: 33.0,
          lon: -98.0,
          status: :good,
          notes: "old"
        })

      conn = log_in_user(conn, admin)
      {:ok, lv, _html} = live(conn, ~p"/rover-locations")

      lv
      |> element("button[phx-click=edit][phx-value-id='#{theirs.id}']")
      |> render_click()

      lv
      |> form("#location-form",
        location: %{
          lat: "33.0",
          lon: "-98.0",
          status: "bad",
          notes: "admin override"
        }
      )
      |> render_submit()

      updated = Microwaveprop.Repo.get(Location, theirs.id)
      assert updated.notes == "admin override"
      assert updated.status == :bad
    end
  end
end
