defmodule MvWeb.MemberLive.IndexMembershipFeeStatusTest do
  @moduledoc """
  Tests for membership fee status column in member list view.
  """
  use MvWeb.ConnCase, async: false

  import Phoenix.LiveViewTest

  alias Mv.MembershipFees.MembershipFeeType
  alias Mv.MembershipFees.MembershipFeeCycle

  require Ash.Query

  # Helper to create a membership fee type
  defp create_fee_type(attrs) do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()

    default_attrs = %{
      name: "Test Fee Type #{System.unique_integer([:positive])}",
      amount: Decimal.new("50.00"),
      interval: :yearly
    }

    attrs = Map.merge(default_attrs, attrs)

    MembershipFeeType
    |> Ash.Changeset.for_create(:create, attrs)
    |> Ash.create!(actor: system_actor)
  end

  # Helper to create a member
  defp create_member(attrs) do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()

    default_attrs = %{
      first_name: "Test",
      last_name: "Member",
      email: "test.member.#{System.unique_integer([:positive])}@example.com"
    }

    attrs = Map.merge(default_attrs, attrs)
    {:ok, member} = Mv.Membership.create_member(attrs, actor: system_actor)
    member
  end

  # Helper to create a cycle
  defp create_cycle(member, fee_type, attrs) do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()

    # Delete any auto-generated cycles first to avoid conflicts
    existing_cycles =
      MembershipFeeCycle
      |> Ash.Query.filter(member_id == ^member.id)
      |> Ash.read!(actor: system_actor)

    Enum.each(existing_cycles, fn cycle -> Ash.destroy!(cycle, actor: system_actor) end)

    default_attrs = %{
      cycle_start: ~D[2023-01-01],
      amount: Decimal.new("50.00"),
      member_id: member.id,
      membership_fee_type_id: fee_type.id,
      status: :unpaid
    }

    attrs = Map.merge(default_attrs, attrs)

    MembershipFeeCycle
    |> Ash.Changeset.for_create(:create, attrs)
    |> Ash.create!(actor: system_actor)
  end

  describe "status column display" do
    test "shows status column in member list", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})
      create_cycle(member, fee_type, %{cycle_start: ~D[2023-01-01], status: :paid})

      {:ok, _view, html} = live(conn, "/members")

      # Should show membership fee status column
      assert html =~ "Membership Fee Status" || html =~ "Mitgliedsbeitrag Status"
    end

    test "shows last completed cycle status by default", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})
      create_cycle(member, fee_type, %{cycle_start: ~D[2022-01-01], status: :paid})
      create_cycle(member, fee_type, %{cycle_start: ~D[2023-01-01], status: :unpaid})

      {:ok, view, _html} = live(conn, "/members")

      # Should show unpaid status (2023 is last completed)
      html = render(view)
      assert html =~ "hero-x-circle" || html =~ "unpaid"
    end

    test "toggle switches to current cycle view", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})

      today = Date.utc_today()
      current_year_start = %{today | month: 1, day: 1}

      create_cycle(member, fee_type, %{cycle_start: ~D[2023-01-01], status: :paid})
      create_cycle(member, fee_type, %{cycle_start: current_year_start, status: :suspended})

      {:ok, view, _html} = live(conn, "/members")

      # Toggle to current cycle (use the button in the header, not the one in the column)
      view
      |> element("button[phx-click='toggle_cycle_view'].btn.gap-2")
      |> render_click()

      html = render(view)
      # Should show suspended status (current cycle)
      assert html =~ "hero-pause-circle" || html =~ "suspended"
    end

    test "shows correct color coding for paid status", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})
      create_cycle(member, fee_type, %{cycle_start: ~D[2023-01-01], status: :paid})

      {:ok, view, _html} = live(conn, "/members")

      html = render(view)
      assert html =~ "text-success" || html =~ "hero-check-circle"
    end

    test "shows correct color coding for unpaid status", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})
      create_cycle(member, fee_type, %{cycle_start: ~D[2023-01-01], status: :unpaid})

      {:ok, view, _html} = live(conn, "/members")

      html = render(view)
      assert html =~ "text-error" || html =~ "hero-x-circle"
    end

    test "shows correct color coding for suspended status", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})
      create_cycle(member, fee_type, %{cycle_start: ~D[2023-01-01], status: :suspended})

      {:ok, view, _html} = live(conn, "/members")

      html = render(view)
      assert html =~ "text-base-content/60" || html =~ "hero-pause-circle"
    end

    test "handles members without cycles gracefully", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})
      # No cycles created

      {:ok, view, _html} = live(conn, "/members")

      html = render(view)
      # Should not crash, may show empty or default state
      assert html =~ member.first_name
    end
  end

  describe "filters" do
    test "filter unpaid in last cycle works", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})

      # Member with unpaid last cycle
      member1 = create_member(%{first_name: "UnpaidMember", membership_fee_type_id: fee_type.id})
      create_cycle(member1, fee_type, %{cycle_start: ~D[2023-01-01], status: :unpaid})

      # Member with paid last cycle
      member2 = create_member(%{first_name: "PaidMember", membership_fee_type_id: fee_type.id})
      create_cycle(member2, fee_type, %{cycle_start: ~D[2023-01-01], status: :paid})

      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      # Verify cycles exist in database
      cycles1 =
        MembershipFeeCycle
        |> Ash.Query.filter(member_id == ^member1.id)
        |> Ash.read!(actor: system_actor)

      cycles2 =
        MembershipFeeCycle
        |> Ash.Query.filter(member_id == ^member2.id)
        |> Ash.read!(actor: system_actor)

      refute Enum.empty?(cycles1)
      refute Enum.empty?(cycles2)

      {:ok, _view, html} = live(conn, "/members?cycle_status_filter=unpaid")

      assert html =~ "UnpaidMember"
      refute html =~ "PaidMember"
    end

    test "filter unpaid in current cycle works", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})

      today = Date.utc_today()
      current_year_start = %{today | month: 1, day: 1}

      # Member with unpaid current cycle
      member1 = create_member(%{first_name: "UnpaidCurrent", membership_fee_type_id: fee_type.id})
      create_cycle(member1, fee_type, %{cycle_start: current_year_start, status: :unpaid})

      # Member with paid current cycle
      member2 = create_member(%{first_name: "PaidCurrent", membership_fee_type_id: fee_type.id})
      create_cycle(member2, fee_type, %{cycle_start: current_year_start, status: :paid})

      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      # Verify cycles exist in database
      cycles1 =
        MembershipFeeCycle
        |> Ash.Query.filter(member_id == ^member1.id)
        |> Ash.read!(actor: system_actor)

      cycles2 =
        MembershipFeeCycle
        |> Ash.Query.filter(member_id == ^member2.id)
        |> Ash.read!(actor: system_actor)

      refute Enum.empty?(cycles1)
      refute Enum.empty?(cycles2)

      {:ok, _view, html} =
        live(conn, "/members?cycle_status_filter=unpaid&show_current_cycle=true")

      assert html =~ "UnpaidCurrent"
      refute html =~ "PaidCurrent"
    end
  end

  @moduletag :slow
  describe "performance" do
    test "loads cycles efficiently without N+1 queries", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})

      # Create multiple members with cycles
      Enum.each(1..5, fn _ ->
        member = create_member(%{membership_fee_type_id: fee_type.id})
        create_cycle(member, fee_type, %{cycle_start: ~D[2023-01-01], status: :paid})
      end)

      {:ok, _view, html} = live(conn, "/members")

      # Should render without errors (N+1 would cause performance issues)
      assert html =~ "Members" || html =~ "Mitglieder"
    end
  end
end
