defmodule MvWeb.Components.SortHeaderComponentTest do
  use MvWeb.ConnCase, async: true
  import Phoenix.LiveViewTest

  describe "rendering" do
    test "renders with correct attributes", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      # Test that the component renders with correct attributes
      assert has_element?(view, "[data-testid='first_name']")
      assert has_element?(view, "button[phx-value-field='city']")
      assert has_element?(view, "button[phx-value-field='first_name']", "First name")
    end

    test "renders all sortable headers", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      sortable_fields = [
        :first_name,
        :email,
        :street,
        :house_number,
        :postal_code,
        :city,
        :join_date
      ]

      for field <- sortable_fields do
        assert has_element?(view, "button[phx-value-field='#{field}']")
      end
    end

    test "renders correct labels", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      # Test specific labels
      assert has_element?(view, "button[phx-value-field='first_name']", "First name")
      assert has_element?(view, "button[phx-value-field='email']", "Email")
      assert has_element?(view, "button[phx-value-field='city']", "City")
    end
  end

  describe "sort icons" do
    test "shows neutral icon for specific field when not sorted", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      # The neutral icon has the opcity class we can test for
      # Test that EMAIL field specifically shows neutral icon
      assert has_element?(view, "[data-testid='email'] .opacity-40")

      # Test that CITY field specifically shows neutral icon
      assert has_element?(view, "[data-testid='city'] .opacity-40")
    end

    test "shows ascending icon for specific field when sorted ascending", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, html} = live(conn, "/members?query=&sort_field=city&sort_order=asc")

      # Test that FIRST_NAME field specifically shows ascending icon
      # Test CSS classes - no opacity for active state
      refute has_element?(view, "[data-testid='city'] .opacity-40")

      # Test that OTHER fields still show neutral icons
      assert has_element?(view, "[data-testid='first_name'] .opacity-40")

      # Test HTML content - should contain chevronup AND chevron up down
      assert html =~ "hero-chevron-up"
      assert html =~ "hero-chevron-up-down"

      # Count occurrences to ensure only one ascending icon
      up_count = html |> String.split("hero-chevron-up ") |> length() |> Kernel.-(1)
      # Should be exactly one chevronup icon
      assert up_count == 1
    end

    test "shows descending icon for specific field when sorted descending", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, _view, html} = live(conn, "/members?query=&sort_field=email&sort_order=desc")

      # Count occurrences to ensure only one descending icon
      down_count = html |> String.split("hero-chevron-down ") |> length() |> Kernel.-(1)
      # Should be exactly one chevrondown icon
      assert down_count == 1
    end

    test "multiple fields can have different icon states", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members?query=&sort_field=city&sort_order=asc")

      # CITY field should be active (ascending)
      refute has_element?(view, "[data-testid='city'] .opacity-40")

      # All other fields should be neutral
      assert has_element?(view, "[data-testid='first_name'] .opacity-40")
      assert has_element?(view, "[data-testid='email'] .opacity-40")
      assert has_element?(view, "[data-testid='street'] .opacity-40")
      assert has_element?(view, "[data-testid='house_number'] .opacity-40")
      assert has_element?(view, "[data-testid='postal_code'] .opacity-40")
      assert has_element?(view, "[data-testid='join_date'] .opacity-40")
    end

    test "icon state changes correctly when clicking different fields", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      # Start: all fields neutral except first name as default
      assert has_element?(view, "[data-testid='city'] .opacity-40")
      refute has_element?(view, "[data-testid='first_name'] .opacity-40")
      assert has_element?(view, "[data-testid='email'] .opacity-40")

      # Click city - should become active
      view
      |> element("button[phx-value-field='city']")
      |> render_click()

      # city should be active, email should still be neutral
      refute has_element?(view, "[data-testid='city'] .opacity-40")
      assert has_element?(view, "[data-testid='email'] .opacity-40")

      # Click email - should switch active field
      view
      |> element("button[phx-value-field='email']")
      |> render_click()

      # email should be active, city should be neutral again
      refute has_element?(view, "[data-testid='email'] .opacity-40")
      assert has_element?(view, "[data-testid='city'] .opacity-40")
    end

    test "specific field shows correct icon for each sort state", %{conn: conn} do
      conn = conn_with_oidc_user(conn)

      # Test EMAIL field specifically
      {:ok, view, html_asc} = live(conn, "/members?sort_field=email&sort_order=asc")
      assert html_asc =~ "hero-chevron-up"
      refute has_element?(view, "[data-testid='email'] .opacity-40")

      {:ok, view, html_desc} = live(conn, "/members?sort_field=email&sort_order=desc")
      assert html_desc =~ "hero-chevron-down"
      refute has_element?(view, "[data-testid='email'] .opacity-40")

      {:ok, view, html_neutral} = live(conn, "/members")
      assert html_neutral =~ "hero-chevron-up-down"
      assert has_element?(view, "[data-testid='email'] .opacity-40")
    end

    test "icon distribution shows exactly one active sort icon", %{conn: conn} do
      conn = conn_with_oidc_user(conn)

      # Test neutral state - only one field should have active sort icon
      {:ok, _view, html_neutral} = live(conn, "/members")

      # Count active icons (should be exactly 1 - ascending for default sort field)
      up_count = html_neutral |> String.split("hero-chevron-up ") |> length() |> Kernel.-(1)
      down_count = html_neutral |> String.split("hero-chevron-down ") |> length() |> Kernel.-(1)

      assert up_count == 1, "Expected exactly 1 ascending icon, got #{up_count}"
      assert down_count == 0, "Expected 0 descending icons, got #{down_count}"

      # Test descending state
      {:ok, _view, html_desc} = live(conn, "/members?sort_field=first_name&sort_order=desc")

      up_count = html_desc |> String.split("hero-chevron-up ") |> length() |> Kernel.-(1)
      down_count = html_desc |> String.split("hero-chevron-down ") |> length() |> Kernel.-(1)

      assert up_count == 0, "Expected 0 ascending icons, got #{up_count}"
      assert down_count == 1, "Expected exactly 1 descending icon, got #{down_count}"
    end
  end

  describe "accessibility" do
    test "sets aria-label correctly for unsorted state", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      # Check aria-label for unsorted state
      assert has_element?(view, "button[phx-value-field='city'][aria-label='Click to sort']")
    end

    test "sets aria-label correctly for ascending sort", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members?sort_field=first_name&sort_order=asc")

      # Check aria-label for ascending sort
      assert has_element?(view, "button[phx-value-field='first_name'][aria-label='ascending']")
    end

    test "sets aria-label correctly for descending sort", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members?sort_field=first_name&sort_order=desc")

      # Check aria-label for descending sort
      assert has_element?(view, "button[phx-value-field='first_name'][aria-label='descending']")
    end

    test "includes tooltip with correct aria-label", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members?sort_field=first_name&sort_order=asc")

      # Check that tooltip div exists with correct data-tip
      assert has_element?(view, "[data-testid='first_name']")
      assert has_element?(view, "button[phx-value-field='first_name'][aria-label='ascending']")
    end

    test "aria-labels work for all sortable fields", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members?sort_field=email&sort_order=desc")

      # Test aria-labels for different fields
      assert has_element?(view, "button[phx-value-field='email'][aria-label='descending']")

      assert has_element?(
               view,
               "button[phx-value-field='first_name'][aria-label='Click to sort']"
             )

      assert has_element?(view, "button[phx-value-field='city'][aria-label='Click to sort']")
    end
  end

  describe "component behavior" do
    test "clicking triggers sort event on parent LiveView", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      # Click on the first name sort header
      view
      |> element("button[phx-value-field='first_name']")
      |> render_click()

      # The component triggers a "sort" event on the parent LiveView
      # This is tested indirectly through the URL change in integration tests
    end

    test "component handles different field types correctly", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      # Test that different field types render correctly
      assert has_element?(view, "button[phx-value-field='first_name']")
      assert has_element?(view, "button[phx-value-field='email']")
      assert has_element?(view, "button[phx-value-field='join_date']")
    end
  end

  describe "edge cases" do
    test "handles invalid sort field gracefully", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, html} = live(conn, "/members?sort_field=invalid_field&sort_order=asc")

      # Should not crash and should default sorting for first name
      assert html =~ "hero-chevron-up-down"
      refute has_element?(view, "[data-testid='first_name'] .opacity-40")
    end

    test "handles invalid sort order gracefully", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, html} = live(conn, "/members?sort_field=first_name&sort_order=invalid")

      # Should default to ascending
      assert html =~ "hero-chevron-up"
      refute has_element?(view, "[data-testid='first_name'] [aria-label='ascending']")
    end

    test "handles empty sort parameters", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, html} = live(conn, "/members?sort_field=&sort_order=")

      # Should show neutral icons
      assert html =~ "hero-chevron-up-down"
      assert has_element?(view, "[data-testid='city'] .opacity-40")
    end
  end

  describe "icon state transitions" do
    test "icon changes when sorting state changes", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, "/members")

      # Start with neutral state
      assert has_element?(view, "[data-testid='city'] .opacity-40")

      # Click to sort ascending
      view
      |> element("button[phx-value-field='city']")
      |> render_click()

      # Should now be ascending (no opacity class)
      refute has_element?(view, "[data-testid='city'] .opacity-40")
    end

    test "multiple fields can be tested for icon states", %{conn: conn} do
      conn = conn_with_oidc_user(conn)
      {:ok, view, html} = live(conn, "/members?sort_field=email&sort_order=desc")

      # Email should be active (descending)
      assert html =~ "hero-chevron-down"
      refute has_element?(view, "[data-testid='email'] .opacity-40")

      # Other fields should be neutral
      assert has_element?(view, "[data-testid='first_name'] .opacity-40")
      assert has_element?(view, "[data-testid='city'] .opacity-40")
    end
  end
end
