defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
  @moduledoc """
  Integration tests for membership fee UI workflows.
  """
  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

  describe "end-to-end workflows" do
    test "create type → assign to member → view cycles → change status", %{conn: conn} do
      # Create type
      fee_type = create_fee_type(%{name: "Regular", interval: :yearly})

      # Assign to member
      member = create_member(%{membership_fee_type_id: fee_type.id})

      # View cycles
      {:ok, view, html} = live(conn, "/members/#{member.id}")

      assert html =~ "Membership Fees" || html =~ "Mitgliedsbeiträge"

      # Get a cycle
      cycles =
        MembershipFeeCycle
        |> Ash.Query.filter(member_id == ^member.id)
        |> Ash.read!()

      if !Enum.empty?(cycles) do
        cycle = List.first(cycles)

        # Switch to Membership Fees tab
        view
        |> element("button[phx-click='switch_tab'][phx-value-tab='membership_fees']")
        |> render_click()

        # Change status
        view
        |> element("button[phx-click='mark_cycle_status'][phx-value-cycle_id='#{cycle.id}']")
        |> render_click()

        # Verify status changed
        system_actor = Mv.Helpers.SystemActor.get_system_actor()

        updated_cycle =
          Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id),
            actor: system_actor
          )

        assert updated_cycle.status == :paid
      end
    end

    test "change member type → cycles regenerate", %{conn: conn} do
      fee_type1 =
        create_fee_type(%{name: "Type 1", interval: :yearly, amount: Decimal.new("50.00")})

      fee_type2 =
        create_fee_type(%{name: "Type 2", interval: :yearly, amount: Decimal.new("75.00")})

      member = create_member(%{membership_fee_type_id: fee_type1.id})

      # Change type
      {:ok, view, _html} = live(conn, "/members/#{member.id}/edit")

      view
      |> form("#member-form", %{"member[membership_fee_type_id]" => fee_type2.id})
      |> render_submit()

      # Verify cycles regenerated with new amount
      cycles =
        MembershipFeeCycle
        |> Ash.Query.filter(member_id == ^member.id)
        |> Ash.Query.filter(status == :unpaid)
        |> Ash.read!()

      # Future unpaid cycles should have new amount
      Enum.each(cycles, fn cycle ->
        if Date.compare(cycle.cycle_start, Date.utc_today()) != :lt do
          assert Decimal.equal?(cycle.amount, fee_type2.amount)
        end
      end)
    end

    test "update settings → new members get default type", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})

      # Update settings
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      {:ok, settings} = Mv.Membership.get_settings()

      settings
      |> Ash.Changeset.for_update(:update_membership_fee_settings, %{
        default_membership_fee_type_id: fee_type.id
      })
      |> Ash.update!(actor: system_actor)

      # Create new member
      {:ok, view, _html} = live(conn, "/members/new")

      form_data = %{
        "member[first_name]" => "New",
        "member[last_name]" => "Member",
        "member[email]" => "new#{System.unique_integer([:positive])}@example.com"
      }

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

      # Verify member got default type
      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      member =
        Mv.Membership.Member
        |> Ash.Query.filter(email == ^form_data["member[email]"])
        |> Ash.read_one!(actor: system_actor)

      assert member.membership_fee_type_id == fee_type.id
    end

    test "delete cycle → confirmation → cycle deleted", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})

      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      cycle =
        MembershipFeeCycle
        |> Ash.Changeset.for_create(:create, %{
          cycle_start: ~D[2023-01-01],
          amount: Decimal.new("50.00"),
          member_id: member.id,
          membership_fee_type_id: fee_type.id,
          status: :unpaid
        })
        |> Ash.create!(actor: system_actor)

      {:ok, view, _html} = live(conn, "/members/#{member.id}")

      # Switch to Membership Fees tab
      view
      |> element("button[phx-click='switch_tab'][phx-value-tab='membership_fees']")
      |> render_click()

      # Delete cycle with confirmation
      view
      |> element("button[phx-click='delete_cycle'][phx-value-cycle_id='#{cycle.id}']")
      |> render_click()

      # Confirm deletion
      view
      |> element("button[phx-click='confirm_delete_cycle'][phx-value-cycle_id='#{cycle.id}']")
      |> render_click()

      # Verify cycle deleted - Ash.read_one returns {:ok, nil} if not found
      result = MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id) |> Ash.read_one()
      assert result == {:ok, nil}
    end

    test "edit cycle amount → modal → amount updated", %{conn: conn} do
      fee_type = create_fee_type(%{interval: :yearly})
      member = create_member(%{membership_fee_type_id: fee_type.id})

      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      cycle =
        MembershipFeeCycle
        |> Ash.Changeset.for_create(:create, %{
          cycle_start: ~D[2023-01-01],
          amount: Decimal.new("50.00"),
          member_id: member.id,
          membership_fee_type_id: fee_type.id,
          status: :unpaid
        })
        |> Ash.create!(actor: system_actor)

      {:ok, view, _html} = live(conn, "/members/#{member.id}")

      # Switch to Membership Fees tab
      view
      |> element("button[phx-click='switch_tab'][phx-value-tab='membership_fees']")
      |> render_click()

      # Open edit modal by clicking on the amount span
      view
      |> element("span[phx-click='edit_cycle_amount'][phx-value-cycle_id='#{cycle.id}']")
      |> render_click()

      # Update amount
      view
      |> form("form[phx-submit='save_cycle_amount']", %{"amount" => "75.00"})
      |> render_submit()

      # Verify amount updated
      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      updated_cycle =
        Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id),
          actor: system_actor
        )

      assert updated_cycle.amount == Decimal.new("75.00")
    end
  end
end
