defmodule Towerops.Accounts.UserTest do
  use Towerops.DataCase, async: true

  alias Towerops.Accounts.User

  describe "registration_changeset/3" do
    test "accepts first_name and last_name" do
      attrs = %{
        email: "test#{System.unique_integer()}@example.com",
        password: "valid_password123",
        first_name: "John",
        last_name: "Smith",
        privacy_policy_consent: true,
        terms_of_service_consent: true
      }

      changeset = User.registration_changeset(%User{}, attrs)

      assert changeset.valid?, "Changeset errors: #{inspect(changeset.errors)}"
      assert Ecto.Changeset.get_field(changeset, :first_name) == "John"
      assert Ecto.Changeset.get_field(changeset, :last_name) == "Smith"
    end

    test "validates first_name length" do
      attrs = %{
        email: "test#{System.unique_integer()}@example.com",
        password: "valid_password123",
        first_name: String.duplicate("a", 256),
        last_name: "Smith",
        privacy_policy_consent: true,
        terms_of_service_consent: true
      }

      changeset = User.registration_changeset(%User{}, attrs)

      refute changeset.valid?
      assert "should be at most 100 character(s)" in errors_on(changeset).first_name
    end

    test "validates last_name length" do
      attrs = %{
        email: "test#{System.unique_integer()}@example.com",
        password: "valid_password123",
        first_name: "John",
        last_name: String.duplicate("a", 256),
        privacy_policy_consent: true,
        terms_of_service_consent: true
      }

      changeset = User.registration_changeset(%User{}, attrs)

      refute changeset.valid?
      assert "should be at most 100 character(s)" in errors_on(changeset).last_name
    end
  end

  describe "profile_changeset/2" do
    test "accepts first_name and last_name updates" do
      user = %User{first_name: "John", last_name: "Smith"}

      attrs = %{first_name: "Jane", last_name: "Doe"}
      changeset = User.profile_changeset(user, attrs)

      assert changeset.valid?
      assert Ecto.Changeset.get_change(changeset, :first_name) == "Jane"
      assert Ecto.Changeset.get_change(changeset, :last_name) == "Doe"
    end

    test "validates first_name length in profile update" do
      user = %User{first_name: "John", last_name: "Smith"}

      attrs = %{first_name: String.duplicate("a", 256)}
      changeset = User.profile_changeset(user, attrs)

      refute changeset.valid?
      assert "should be at most 100 character(s)" in errors_on(changeset).first_name
    end

    test "validates last_name length in profile update" do
      user = %User{first_name: "John", last_name: "Smith"}

      attrs = %{last_name: String.duplicate("a", 256)}
      changeset = User.profile_changeset(user, attrs)

      refute changeset.valid?
      assert "should be at most 100 character(s)" in errors_on(changeset).last_name
    end

    test "does not accept name field (deprecated)" do
      user = %User{first_name: "John", last_name: "Smith"}

      attrs = %{name: "Jane Doe"}
      changeset = User.profile_changeset(user, attrs)

      # name field should not be cast
      assert Ecto.Changeset.get_change(changeset, :name) == nil
    end

    test "accepts time_format field" do
      user = %User{time_format: "24h"}

      attrs = %{time_format: "12h"}
      changeset = User.profile_changeset(user, attrs)

      assert changeset.valid?
      assert Ecto.Changeset.get_change(changeset, :time_format) == "12h"
    end

    test "validates time_format is 12h or 24h" do
      user = %User{time_format: "24h"}

      attrs = %{time_format: "invalid"}
      changeset = User.profile_changeset(user, attrs)

      refute changeset.valid?
      assert "is invalid" in errors_on(changeset).time_format
    end
  end

  describe "full_name/1" do
    test "returns full name when both first and last name are present" do
      user = %User{first_name: "John", last_name: "Smith"}
      assert User.full_name(user) == "John Smith"
    end

    test "returns first name when only first name is present" do
      user = %User{first_name: "John", last_name: nil}
      assert User.full_name(user) == "John"
    end

    test "returns last name when only last name is present" do
      user = %User{first_name: nil, last_name: "Smith"}
      assert User.full_name(user) == "Smith"
    end

    test "returns nil when neither name is present" do
      user = %User{first_name: nil, last_name: nil}
      assert User.full_name(user) == nil
    end

    test "handles empty strings as nil" do
      user = %User{first_name: "", last_name: ""}
      assert User.full_name(user) == nil
    end
  end
end
