# Script for populating the database. You can run it as:
#
#     mix run priv/repo/seeds.exs
#

alias Mv.Accounts
alias Mv.Membership
alias Mv.MembershipFees.CycleGenerator
alias Mv.MembershipFees.MembershipFeeType

require Ash.Query

# Create example membership fee types (no admin user yet; skip authorization for bootstrap)
for fee_type_attrs <- [
      %{
        name: "Standard (Jährlich)",
        amount: Decimal.new("120.00"),
        interval: :yearly,
        description: "Standard jährlicher Mitgliedsbeitrag"
      },
      %{
        name: "Standard (Halbjährlich)",
        amount: Decimal.new("65.00"),
        interval: :half_yearly,
        description: "Standard halbjährlicher Mitgliedsbeitrag"
      },
      %{
        name: "Standard (Vierteljährlich)",
        amount: Decimal.new("35.00"),
        interval: :quarterly,
        description: "Standard vierteljährlicher Mitgliedsbeitrag"
      },
      %{
        name: "Standard (Monatlich)",
        amount: Decimal.new("12.00"),
        interval: :monthly,
        description: "Standard monatlicher Mitgliedsbeitrag"
      }
    ] do
  MembershipFeeType
  |> Ash.Changeset.for_create(:create, fee_type_attrs)
  |> Ash.create!(
    upsert?: true,
    upsert_identity: :unique_name,
    authorize?: false,
    domain: Mv.MembershipFees
  )
end

for attrs <- [
      # Basic example fields (for testing)
      %{
        name: "String Field",
        value_type: :string,
        description: "Example for a field of type string",
        required: false
      },
      %{
        name: "Date Field",
        value_type: :date,
        description: "Example for a field of type date",
        required: false
      },
      %{
        name: "Boolean Field",
        value_type: :boolean,
        description: "Example for a field of type boolean",
        required: false
      },
      %{
        name: "Email Field",
        value_type: :email,
        description: "Example for a field of type email",
        required: false
      },
      # Realistic custom fields
      %{
        name: "Membership Number",
        value_type: :string,
        description: "Unique membership identification number",
        required: false
      },
      %{
        name: "Emergency Contact",
        value_type: :string,
        description: "Emergency contact person name and phone",
        required: false
      },
      %{
        name: "T-Shirt Size",
        value_type: :string,
        description: "T-Shirt size for events (XS, S, M, L, XL, XXL)",
        required: false
      },
      %{
        name: "Newsletter Subscription",
        value_type: :boolean,
        description: "Whether member wants to receive newsletter",
        required: false
      },
      %{
        name: "Date of Last Medical Check",
        value_type: :date,
        description: "Date of last medical examination",
        required: false
      },
      %{
        name: "Secondary Email",
        value_type: :email,
        description: "Alternative email address",
        required: false
      },
      %{
        name: "Membership Type",
        value_type: :string,
        description: "Type of membership (e.g., Regular, Student, Senior)",
        required: false
      },
      %{
        name: "Parking Permit",
        value_type: :boolean,
        description: "Whether member has parking permit",
        required: false
      }
    ] do
  # Bootstrap: no admin user yet; CustomField create requires admin, so skip authorization
  Membership.create_custom_field!(
    attrs,
    upsert?: true,
    upsert_identity: :unique_name,
    authorize?: false
  )
end

# Admin email: default for dev/test so seed_admin has a target
admin_email = System.get_env("ADMIN_EMAIL") || "admin@localhost"
System.put_env("ADMIN_EMAIL", admin_email)

# In dev/test, set fallback password so seed_admin creates the admin user when none is set
if Mix.env() in [:dev, :test] and is_nil(System.get_env("ADMIN_PASSWORD")) and
     is_nil(System.get_env("ADMIN_PASSWORD_FILE")) do
  System.put_env("ADMIN_PASSWORD", "testpassword")
end

# Create all authorization roles (idempotent - creates only if they don't exist)
# Roles are created using create_role_with_system_flag to allow setting is_system_role
role_configs = [
  %{
    name: "Mitglied",
    description: "Default member role with access to own data only",
    permission_set_name: "own_data",
    is_system_role: true
  },
  %{
    name: "Vorstand",
    description: "Board member with read access to all member data",
    permission_set_name: "read_only",
    is_system_role: false
  },
  %{
    name: "Kassenwart",
    description: "Treasurer with full member and payment management",
    permission_set_name: "normal_user",
    is_system_role: false
  },
  %{
    name: "Buchhaltung",
    description: "Accounting with read-only access for auditing",
    permission_set_name: "read_only",
    is_system_role: false
  },
  %{
    name: "Admin",
    description: "Administrator with unrestricted access",
    permission_set_name: "admin",
    is_system_role: false
  }
]

# Create or update each role
Enum.each(role_configs, fn role_data ->
  # Bind role name to variable to avoid issues with ^ pinning in macros
  role_name = role_data.name

  case Mv.Authorization.Role
       |> Ash.Query.filter(name == ^role_name)
       |> Ash.read_one(authorize?: false, domain: Mv.Authorization) do
    {:ok, existing_role} when not is_nil(existing_role) ->
      # Role exists - update if needed (preserve is_system_role)
      if existing_role.permission_set_name != role_data.permission_set_name or
           existing_role.description != role_data.description do
        existing_role
        |> Ash.Changeset.for_update(:update_role, %{
          description: role_data.description,
          permission_set_name: role_data.permission_set_name
        })
        |> Ash.update!(authorize?: false, domain: Mv.Authorization)
      end

    {:ok, nil} ->
      # Role doesn't exist - create it
      Mv.Authorization.Role
      |> Ash.Changeset.for_create(:create_role_with_system_flag, role_data)
      |> Ash.create!(authorize?: false, domain: Mv.Authorization)

    {:error, error} ->
      IO.puts("Warning: Failed to check for role #{role_data.name}: #{inspect(error)}")
  end
end)

# Get admin role for assignment to admin user
admin_role =
  case Mv.Authorization.Role
       |> Ash.Query.filter(name == "Admin")
       |> Ash.read_one(authorize?: false, domain: Mv.Authorization) do
    {:ok, role} when not is_nil(role) -> role
    _ -> nil
  end

if is_nil(admin_role) do
  raise "Failed to create or find admin role. Cannot proceed with member seeding."
end

# Create/update admin user via Release.seed_admin (uses ADMIN_EMAIL, ADMIN_PASSWORD / ADMIN_PASSWORD_FILE).
# Reduces duplication and exercises the same path as production entrypoint.
Mv.Release.seed_admin()

# Load admin user with role for use as actor in member operations
# This ensures all member operations have proper authorization
admin_user_with_role =
  case Accounts.User
       |> Ash.Query.filter(email == ^admin_email)
       |> Ash.read_one(domain: Mv.Accounts, authorize?: false) do
    {:ok, user} when not is_nil(user) ->
      user
      |> Ash.load!(:role, authorize?: false)

    {:ok, nil} ->
      raise "Admin user not found after creation/assignment"

    {:error, error} ->
      raise "Failed to load admin user: #{inspect(error)}"
  end

# Create system user for systemic operations (email sync, validations, cycle generation)
# This user is used by Mv.Helpers.SystemActor for operations that must always run
# Email is configurable via SYSTEM_ACTOR_EMAIL environment variable
system_user_email = Mv.Helpers.SystemActor.system_user_email()

case Accounts.User
     |> Ash.Query.filter(email == ^system_user_email)
     |> Ash.read_one(domain: Mv.Accounts, authorize?: false) do
  {:ok, existing_system_user} when not is_nil(existing_system_user) ->
    # System user already exists - ensure it has admin role
    # Use authorize?: false for bootstrap; :update_internal bypasses system-user modification block
    existing_system_user
    |> Ash.Changeset.for_update(:update_internal, %{})
    |> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
    |> Ash.update!(authorize?: false)

  {:ok, nil} ->
    # System user doesn't exist - create it with admin role
    # SECURITY: System user must NOT be able to log in:
    # - No password (hashed_password = nil) - prevents password login
    # - No OIDC ID (oidc_id = nil) - prevents OIDC login
    # - This user is ONLY for internal system operations via SystemActor
    # If either hashed_password or oidc_id is set, the user could potentially log in
    # Use authorize?: false for bootstrap - system user creation happens before system actor exists
    Accounts.create_user!(%{email: system_user_email},
      upsert?: true,
      upsert_identity: :unique_email,
      authorize?: false
    )
    |> Ash.Changeset.for_update(:update_internal, %{})
    |> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
    |> Ash.update!(authorize?: false)

  {:error, error} ->
    # Log error but don't fail seeds - SystemActor will fall back to admin user
    IO.puts("Warning: Failed to create system user: #{inspect(error)}")
    IO.puts("SystemActor will fall back to admin user (#{admin_email})")
end

# Load all membership fee types for assignment (admin actor for authorization)
# Sort by name to ensure deterministic order
all_fee_types =
  MembershipFeeType
  |> Ash.Query.sort(name: :asc)
  |> Ash.read!(actor: admin_user_with_role, domain: Mv.MembershipFees)
  |> Enum.to_list()

# Create sample members for testing - use upsert to prevent duplicates
# Member 1: Hans - All cycles paid
# Member 2: Greta - All cycles unpaid
# Member 3: Friedrich - Mixed cycles (paid, unpaid, suspended)
# Member 4: Marianne - No membership fee type
member_attrs_list = [
  %{
    first_name: "Hans",
    last_name: "Müller",
    email: "hans.mueller@example.de",
    join_date: ~D[2023-01-15],
    city: "München",
    street: "Hauptstraße",
    house_number: "42",
    postal_code: "80331",
    membership_fee_type_id: Enum.at(all_fee_types, 0).id,
    cycle_status: :all_paid
  },
  %{
    first_name: "Greta",
    last_name: "Schmidt",
    email: "greta.schmidt@example.de",
    join_date: ~D[2023-02-01],
    city: "Hamburg",
    street: "Lindenstraße",
    house_number: "17",
    postal_code: "20095",
    notes: "Interessiert an Fortgeschrittenen-Kursen",
    membership_fee_type_id: Enum.at(all_fee_types, 1).id,
    cycle_status: :all_unpaid
  },
  %{
    first_name: "Friedrich",
    last_name: "Wagner",
    email: "friedrich.wagner@example.de",
    join_date: ~D[2022-11-10],
    city: "Berlin",
    street: "Kastanienallee",
    house_number: "8",
    membership_fee_type_id: Enum.at(all_fee_types, 2).id,
    cycle_status: :mixed
  },
  %{
    first_name: "Marianne",
    last_name: "Wagner",
    email: "marianne.wagner@example.de",
    join_date: ~D[2022-11-10],
    city: "Berlin",
    street: "Kastanienallee",
    house_number: "8"
    # No membership_fee_type_id - member without fee type
  }
]

# Create members and generate cycles
Enum.each(member_attrs_list, fn member_attrs ->
  cycle_status = Map.get(member_attrs, :cycle_status)
  member_attrs_without_status = Map.delete(member_attrs, :cycle_status)

  # Use upsert to prevent duplicates based on email
  # First create/update member without membership_fee_type_id to avoid overwriting existing assignments
  member_attrs_without_fee_type = Map.delete(member_attrs_without_status, :membership_fee_type_id)

  member =
    Membership.create_member!(member_attrs_without_fee_type,
      upsert?: true,
      upsert_identity: :unique_email,
      actor: admin_user_with_role
    )

  # Only set membership_fee_type_id if member doesn't have one yet (idempotent)
  final_member =
    if is_nil(member.membership_fee_type_id) and
         Map.has_key?(member_attrs_without_status, :membership_fee_type_id) do
      {:ok, updated} =
        Membership.update_member(
          member,
          %{
            membership_fee_type_id: member_attrs_without_status.membership_fee_type_id
          },
          actor: admin_user_with_role
        )

      updated
    else
      member
    end

  # Generate cycles if member has a fee type
  if final_member.membership_fee_type_id do
    # Load member with cycles to check if they already exist (actor required for auth)
    member_with_cycles =
      Ash.load!(final_member, :membership_fee_cycles, actor: admin_user_with_role)

    # Only generate if no cycles exist yet (to avoid duplicates on re-run)
    cycles =
      if Enum.empty?(member_with_cycles.membership_fee_cycles) do
        # Generate cycles
        {:ok, new_cycles, _notifications} =
          CycleGenerator.generate_cycles_for_member(final_member.id,
            skip_lock?: true,
            actor: admin_user_with_role
          )

        new_cycles
      else
        # Use existing cycles
        member_with_cycles.membership_fee_cycles
      end

    # Set cycle statuses based on member type
    if cycle_status do
      cycles
      |> Enum.sort_by(& &1.cycle_start, Date)
      |> Enum.with_index()
      |> Enum.each(fn {cycle, index} ->
        status =
          case cycle_status do
            :all_paid ->
              :paid

            :all_unpaid ->
              :unpaid

            :mixed ->
              # Mix: first paid, second unpaid, third suspended, then repeat
              case rem(index, 3) do
                0 -> :paid
                1 -> :unpaid
                2 -> :suspended
              end
          end

        # Only update if status is different
        if cycle.status != status do
          cycle
          |> Ash.Changeset.for_update(:update, %{status: status})
          |> Ash.update!(actor: admin_user_with_role, domain: Mv.MembershipFees)
        end
      end)
    end
  end
end)

# Create additional users for user-member linking examples (no password by default)
# Only admin gets a password (admin_set_password when created); all other users have no password.
additional_users = [
  %{email: "hans.mueller@example.de"},
  %{email: "greta.schmidt@example.de"},
  %{email: "maria.weber@example.de"},
  %{email: "thomas.klein@example.de"}
]

created_users =
  Enum.map(additional_users, fn user_attrs ->
    user =
      Accounts.create_user!(user_attrs,
        upsert?: true,
        upsert_identity: :unique_email,
        actor: admin_user_with_role
      )

    # Reload user to ensure all fields (including member_id) are loaded
    Accounts.User
    |> Ash.Query.filter(id == ^user.id)
    |> Ash.read_one!(domain: Mv.Accounts, actor: admin_user_with_role)
  end)

# Create members with linked users to demonstrate the 1:1 relationship
# Only create if users don't already have members
linked_members = [
  %{
    first_name: "Maria",
    last_name: "Weber",
    email: "maria.weber@example.de",
    join_date: ~D[2023-03-15],
    city: "Frankfurt",
    street: "Goetheplatz",
    house_number: "5",
    postal_code: "60313",
    notes: "Linked to user account",
    # Link to the third user (maria.weber@example.de)
    user: Enum.at(created_users, 2)
  },
  %{
    first_name: "Thomas",
    last_name: "Klein",
    email: "thomas.klein@example.de",
    join_date: ~D[2023-04-01],
    city: "Köln",
    street: "Rheinstraße",
    house_number: "23",
    postal_code: "50667",
    notes: "Linked to user account - needs payment follow-up",
    # Link to the fourth user (thomas.klein@example.de)
    user: Enum.at(created_users, 3)
  }
]

# Create the linked members - use upsert to prevent duplicates
# Assign fee types to linked members using round-robin
# Continue from where we left off with the previous members
Enum.with_index(linked_members)
|> Enum.each(fn {member_attrs, index} ->
  user = member_attrs.user
  member_attrs_without_user = Map.delete(member_attrs, :user)

  # Use upsert to prevent duplicates based on email
  # First create/update member without membership_fee_type_id to avoid overwriting existing assignments
  member_attrs_without_fee_type = Map.delete(member_attrs_without_user, :membership_fee_type_id)

  # Check if user already has a member
  member =
    if user.member_id == nil do
      # User is free, create member and link - use upsert to prevent duplicates
      # Use authorize?: false for User lookup during relationship management (bootstrap phase)
      Membership.create_member!(
        Map.put(member_attrs_without_fee_type, :user, %{id: user.id}),
        upsert?: true,
        upsert_identity: :unique_email,
        actor: admin_user_with_role,
        authorize?: false
      )
    else
      # User already has a member, just create the member without linking - use upsert to prevent duplicates
      Membership.create_member!(member_attrs_without_fee_type,
        upsert?: true,
        upsert_identity: :unique_email,
        actor: admin_user_with_role
      )
    end

  # Only set membership_fee_type_id if member doesn't have one yet (idempotent)
  final_member =
    if is_nil(member.membership_fee_type_id) do
      # Assign deterministically using round-robin
      # Start from where previous members ended (3 members before this)
      fee_type_index = rem(3 + index, length(all_fee_types))
      fee_type = Enum.at(all_fee_types, fee_type_index)

      {:ok, updated} =
        Membership.update_member(member, %{membership_fee_type_id: fee_type.id},
          actor: admin_user_with_role
        )

      updated
    else
      member
    end

  # Generate cycles for linked members
  if final_member.membership_fee_type_id do
    # Load member with cycles to check if they already exist (actor required for auth)
    member_with_cycles =
      Ash.load!(final_member, :membership_fee_cycles, actor: admin_user_with_role)

    # Only generate if no cycles exist yet (to avoid duplicates on re-run)
    cycles =
      if Enum.empty?(member_with_cycles.membership_fee_cycles) do
        # Generate cycles
        {:ok, new_cycles, _notifications} =
          CycleGenerator.generate_cycles_for_member(final_member.id,
            skip_lock?: true,
            actor: admin_user_with_role
          )

        new_cycles
      else
        # Use existing cycles
        member_with_cycles.membership_fee_cycles
      end

    # Set some cycles to paid for linked members (mixed status)
    cycles
    |> Enum.sort_by(& &1.cycle_start, Date)
    |> Enum.with_index()
    |> Enum.each(fn {cycle, index} ->
      # Every other cycle is paid, rest unpaid
      status = if rem(index, 2) == 0, do: :paid, else: :unpaid

      # Only update if status is different
      if cycle.status != status do
        cycle
        |> Ash.Changeset.for_update(:update, %{status: status})
        |> Ash.update!(actor: admin_user_with_role, domain: Mv.MembershipFees)
      end
    end)
  end
end)

# Create example groups (idempotent: create only if name does not exist)
group_configs = [
  %{name: "Vorstand", description: "Gremium Vorstand"},
  %{name: "Trainer*innen", description: "Alle lizenzierten Trainer*innen"},
  %{name: "Jugend", description: "Jugendbereich"},
  %{name: "Newsletter", description: "Empfänger*innen Newsletter"}
]

existing_groups =
  case Membership.list_groups(actor: admin_user_with_role) do
    {:ok, list} -> list
    {:error, _} -> []
  end

existing_names_lower = MapSet.new(existing_groups, &String.downcase(&1.name))

seed_groups =
  Enum.reduce(group_configs, %{}, fn config, acc ->
    name = config.name

    if MapSet.member?(existing_names_lower, String.downcase(name)) do
      group = Enum.find(existing_groups, &(String.downcase(&1.name) == String.downcase(name)))
      Map.put(acc, name, group)
    else
      group =
        Membership.create_group!(%{name: name, description: config.description},
          actor: admin_user_with_role
        )

      Map.put(acc, name, group)
    end
  end)

# Create sample custom field values for some members
all_members = Ash.read!(Membership.Member, actor: admin_user_with_role)
all_custom_fields = Ash.read!(Membership.CustomField, actor: admin_user_with_role)

# Helper function to find custom field by name
find_field = fn name -> Enum.find(all_custom_fields, &(&1.name == name)) end
find_member = fn email -> Enum.find(all_members, &(&1.email == email)) end

# Assign seed members to groups (idempotent: duplicate create_member_group is skipped)
member_group_assignments = [
  {"hans.mueller@example.de", ["Vorstand", "Newsletter"]},
  {"greta.schmidt@example.de", ["Jugend", "Newsletter"]},
  {"friedrich.wagner@example.de", ["Trainer*innen"]},
  {"maria.weber@example.de", ["Newsletter"]},
  {"thomas.klein@example.de", ["Newsletter"]}
]

Enum.each(member_group_assignments, fn {email, group_names} ->
  member = find_member.(email)

  if member do
    Enum.each(group_names, fn group_name ->
      group = seed_groups[group_name]

      if group do
        case Membership.create_member_group(
               %{member_id: member.id, group_id: group.id},
               actor: admin_user_with_role
             ) do
          {:ok, _} -> :ok
          {:error, _} -> :ok
        end
      end
    end)
  end
end)

# Add custom field values for Hans Müller
if hans = find_member.("hans.mueller@example.de") do
  [
    {find_field.("Membership Number"),
     %{"_union_type" => "string", "_union_value" => "M-2023-001"}},
    {find_field.("T-Shirt Size"), %{"_union_type" => "string", "_union_value" => "L"}},
    {find_field.("Newsletter Subscription"),
     %{"_union_type" => "boolean", "_union_value" => true}},
    {find_field.("Membership Type"), %{"_union_type" => "string", "_union_value" => "Regular"}},
    {find_field.("Parking Permit"), %{"_union_type" => "boolean", "_union_value" => true}},
    {find_field.("Secondary Email"),
     %{"_union_type" => "email", "_union_value" => "hans.m@private.de"}}
  ]
  |> Enum.each(fn {field, value} ->
    if field do
      Membership.CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: hans.id,
        custom_field_id: field.id,
        value: value
      })
      |> Ash.create!(
        upsert?: true,
        upsert_identity: :unique_custom_field_per_member,
        actor: admin_user_with_role
      )
    end
  end)
end

# Add custom field values for Greta Schmidt
if greta = find_member.("greta.schmidt@example.de") do
  [
    {find_field.("Membership Number"),
     %{"_union_type" => "string", "_union_value" => "M-2023-015"}},
    {find_field.("T-Shirt Size"), %{"_union_type" => "string", "_union_value" => "M"}},
    {find_field.("Newsletter Subscription"),
     %{"_union_type" => "boolean", "_union_value" => true}},
    {find_field.("Membership Type"), %{"_union_type" => "string", "_union_value" => "Student"}},
    {find_field.("Emergency Contact"),
     %{"_union_type" => "string", "_union_value" => "Anna Schmidt, +49301234567"}}
  ]
  |> Enum.each(fn {field, value} ->
    if field do
      Membership.CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: greta.id,
        custom_field_id: field.id,
        value: value
      })
      |> Ash.create!(
        upsert?: true,
        upsert_identity: :unique_custom_field_per_member,
        actor: admin_user_with_role
      )
    end
  end)
end

# Add custom field values for Friedrich Wagner
if friedrich = find_member.("friedrich.wagner@example.de") do
  [
    {find_field.("Membership Number"),
     %{"_union_type" => "string", "_union_value" => "M-2022-042"}},
    {find_field.("T-Shirt Size"), %{"_union_type" => "string", "_union_value" => "XL"}},
    {find_field.("Newsletter Subscription"),
     %{"_union_type" => "boolean", "_union_value" => false}},
    {find_field.("Membership Type"), %{"_union_type" => "string", "_union_value" => "Senior"}},
    {find_field.("Parking Permit"), %{"_union_type" => "boolean", "_union_value" => false}},
    {find_field.("Date of Last Medical Check"),
     %{"_union_type" => "date", "_union_value" => ~D[2024-03-15]}}
  ]
  |> Enum.each(fn {field, value} ->
    if field do
      Membership.CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: friedrich.id,
        custom_field_id: field.id,
        value: value
      })
      |> Ash.create!(
        upsert?: true,
        upsert_identity: :unique_custom_field_per_member,
        actor: admin_user_with_role
      )
    end
  end)
end

# Create or update global settings (singleton)
default_club_name = System.get_env("ASSOCIATION_NAME") || "Club Name"

case Membership.get_settings() do
  {:ok, existing_settings} ->
    # Settings exist, update if club_name is different from env var
    # Also ensure exit_date is set to false by default if not already configured
    updates =
      %{}
      |> then(fn acc ->
        if existing_settings.club_name != default_club_name,
          do: Map.put(acc, :club_name, default_club_name),
          else: acc
      end)
      |> then(fn acc ->
        visibility_config = existing_settings.member_field_visibility || %{}
        # Ensure exit_date is set to false if not already configured
        if not Map.has_key?(visibility_config, "exit_date") and
             not Map.has_key?(visibility_config, :exit_date) do
          updated_visibility = Map.put(visibility_config, "exit_date", false)
          Map.put(acc, :member_field_visibility, updated_visibility)
        else
          acc
        end
      end)

    if map_size(updates) > 0 do
      {:ok, _updated} = Membership.update_settings(existing_settings, updates)
    end

  {:ok, nil} ->
    # Settings don't exist yet, create with exit_date defaulting to false
    {:ok, _settings} =
      Membership.Setting
      |> Ash.Changeset.for_create(:create, %{
        club_name: default_club_name,
        member_field_visibility: %{"exit_date" => false}
      })
      |> Ash.create!()
end

IO.puts("✅ Seeds completed successfully!")
IO.puts("📝 Created sample data:")
IO.puts("   - Global settings: club_name = #{default_club_name}")
IO.puts("   - Membership fee types: 4 types (Yearly, Half-yearly, Quarterly, Monthly)")
IO.puts("   - Custom fields: 12 fields (String, Date, Boolean, Email, + 8 realistic fields)")

password_configured =
  System.get_env("ADMIN_PASSWORD") != nil or System.get_env("ADMIN_PASSWORD_FILE") != nil

IO.puts(
  "   - Admin user: #{admin_email} (password: #{if password_configured, do: "set", else: "not set"})"
)

IO.puts("   - Sample members: Hans, Greta, Friedrich")
IO.puts("   - Groups: Vorstand, Trainer*innen, Jugend, Newsletter (with members assigned)")

IO.puts(
  "   - Additional users: hans.mueller@example.de, greta.schmidt@example.de, maria.weber@example.de, thomas.klein@example.de"
)

IO.puts(
  "   - Linked members: Maria Weber ↔ maria.weber@example.de, Thomas Klein ↔ thomas.klein@example.de"
)

IO.puts(
  "   - Custom field values: Sample data for Hans (6 fields), Greta (5 fields), Friedrich (6 fields)"
)

IO.puts("🔗 Visit the application to see user-member relationships and custom fields in action!")
