defmodule MvWeb.MembershipFeeTypeLive.FormTest do
  @moduledoc """
  Tests for membership fee types create/edit form.
  """
  use MvWeb.ConnCase, async: false

  import Phoenix.LiveViewTest

  alias Mv.MembershipFees.MembershipFeeType

  require Ash.Query

  setup %{conn: conn} do
    # User must have admin role (or normal_user) to access /membership_fee_types pages
    user = Mv.Fixtures.user_with_role_fixture("admin")
    authenticated_conn = conn_with_password_user(conn, user)
    %{conn: authenticated_conn, user: user}
  end

  # 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

  describe "create form" do
    test "creates new membership fee type", %{conn: conn, user: user} do
      {:ok, view, _html} = live(conn, "/membership_fee_types/new")

      form_data = %{
        "membership_fee_type[name]" => "New Type",
        "membership_fee_type[amount]" => "75.00",
        "membership_fee_type[interval]" => "yearly",
        "membership_fee_type[description]" => "Test description"
      }

      {:error, {:live_redirect, %{to: to}}} =
        view
        |> form("#membership-fee-type-form", form_data)
        |> render_submit()

      assert to == "/membership_fee_types"

      # Verify type was created (use actor so read is authorized)
      type =
        MembershipFeeType
        |> Ash.Query.filter(name == "New Type")
        |> Ash.read_one!(domain: Mv.MembershipFees, actor: user)

      assert type != nil, "Expected membership fee type to be created"
      assert type.amount == Decimal.new("75.00")
      assert type.interval == :yearly
    end

    test "interval field is editable on create", %{conn: conn} do
      {:ok, _view, html} = live(conn, "/membership_fee_types/new")

      # Interval field should be editable (not disabled)
      refute html =~ "disabled" || html =~ "readonly"
    end
  end

  describe "edit form" do
    test "loads existing type data", %{conn: conn} do
      fee_type = create_fee_type(%{name: "Existing Type", amount: Decimal.new("60.00")})

      {:ok, _view, html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit")

      assert html =~ "Existing Type"
      assert html =~ "60" || html =~ "60,00"
    end

    test "interval field is grayed out on edit", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})

      {:ok, _view, html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit")

      # Interval field should be disabled
      assert html =~ "disabled" || html =~ "readonly"
    end

    test "amount change warning displays on edit", %{conn: conn} do
      fee_type = create_fee_type(%{amount: Decimal.new("50.00")})
      create_member(%{membership_fee_type_id: fee_type.id})

      {:ok, view, _html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit")

      # Change amount
      view
      |> form("#membership-fee-type-form", %{"membership_fee_type[amount]" => "75.00"})
      |> render_change()

      # Should show warning in rendered view
      html = render(view)
      assert html =~ "affect" || html =~ "Change Amount"
    end

    test "amount change warning shows correct affected member count", %{conn: conn} do
      fee_type = create_fee_type(%{amount: Decimal.new("50.00")})

      # Create 3 members
      Enum.each(1..3, fn _ ->
        create_member(%{membership_fee_type_id: fee_type.id})
      end)

      {:ok, view, _html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit")

      # Change amount
      html =
        view
        |> form("#membership-fee-type-form", %{"membership_fee_type[amount]" => "75.00"})
        |> render_change()

      # Should show affected count
      assert html =~ "3" || html =~ "members" || html =~ "Mitglieder"
    end

    test "amount change can be confirmed", %{conn: conn, user: user} do
      fee_type = create_fee_type(%{amount: Decimal.new("50.00")})

      {:ok, view, _html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit")

      # Change amount and confirm
      view
      |> form("#membership-fee-type-form", %{"membership_fee_type[amount]" => "75.00"})
      |> render_change()

      view
      |> element("button[phx-click='confirm_amount_change']")
      |> render_click()

      # Submit the form to actually save the change
      view
      |> form("#membership-fee-type-form", %{"membership_fee_type[amount]" => "75.00"})
      |> render_submit()

      # Amount should be updated (use actor so read is authorized)
      updated_type =
        MembershipFeeType
        |> Ash.Query.filter(id == ^fee_type.id)
        |> Ash.read_one!(domain: Mv.MembershipFees, actor: user)

      assert updated_type != nil
      assert updated_type.amount == Decimal.new("75.00")
    end

    test "amount change can be cancelled", %{conn: conn, user: user} do
      fee_type = create_fee_type(%{amount: Decimal.new("50.00")})

      {:ok, view, _html} = live(conn, "/membership_fee_types/#{fee_type.id}/edit")

      # Change amount and cancel
      view
      |> form("#membership-fee-type-form", %{"membership_fee_type[amount]" => "75.00"})
      |> render_change()

      view
      |> element("button[phx-click='cancel_amount_change']")
      |> render_click()

      # Amount should remain unchanged (use actor so read is authorized)
      updated_type =
        MembershipFeeType
        |> Ash.Query.filter(id == ^fee_type.id)
        |> Ash.read_one!(domain: Mv.MembershipFees, actor: user)

      assert updated_type != nil
      assert updated_type.amount == Decimal.new("50.00")
    end

    test "validation errors display correctly", %{conn: conn} do
      {:ok, view, _html} = live(conn, "/membership_fee_types/new")

      # Submit with invalid data
      html =
        view
        |> form("#membership-fee-type-form", %{
          "membership_fee_type[name]" => "",
          "membership_fee_type[amount]" => ""
        })
        |> render_submit()

      # Should show validation errors
      assert html =~ "can't be blank" || html =~ "darf nicht leer sein" || html =~ "required"
    end
  end

  describe "permissions" do
    test "only admin can access", %{conn: conn} do
      # This test assumes non-admin users cannot access
      {:ok, _view, html} = live(conn, "/membership_fee_types/new")

      # Should show the form (admin user in setup)
      assert html =~ "Membership Fee Type" || html =~ "Beitragsart"
    end
  end
end
