defmodule Towerops.ApiTokens.ApiTokenTest do
  use Towerops.DataCase

  import Towerops.AccountsFixtures
  import Towerops.OrganizationsFixtures

  alias Towerops.ApiTokens.ApiToken

  describe "changeset/2" do
    setup do
      user = user_fixture()
      organization = organization_fixture(user.id)
      %{user: user, organization: organization}
    end

    test "valid changeset with all required fields", %{
      user: user,
      organization: organization
    } do
      attrs = %{
        organization_id: organization.id,
        user_id: user.id,
        name: "Test Token",
        token_hash: "abc123"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      assert changeset.valid?
    end

    test "valid changeset without user_id", %{organization: organization} do
      attrs = %{
        organization_id: organization.id,
        name: "Test Token",
        token_hash: "abc123"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      assert changeset.valid?
    end

    test "valid changeset with expires_at", %{organization: organization} do
      expires_at = DateTime.add(DateTime.utc_now(), 30, :day)

      attrs = %{
        organization_id: organization.id,
        name: "Test Token",
        token_hash: "abc123",
        expires_at: expires_at
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      assert changeset.valid?
    end

    test "valid changeset with last_used_at", %{organization: organization} do
      last_used_at = DateTime.utc_now()

      attrs = %{
        organization_id: organization.id,
        name: "Test Token",
        token_hash: "abc123",
        last_used_at: last_used_at
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      assert changeset.valid?
    end

    test "invalid changeset without organization_id", %{user: user} do
      attrs = %{
        user_id: user.id,
        name: "Test Token",
        token_hash: "abc123"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).organization_id
    end

    test "invalid changeset without name", %{organization: organization} do
      attrs = %{
        organization_id: organization.id,
        token_hash: "abc123"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).name
    end

    test "invalid changeset without token_hash", %{organization: organization} do
      attrs = %{
        organization_id: organization.id,
        name: "Test Token"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).token_hash
    end

    test "invalid changeset with blank name", %{organization: organization} do
      attrs = %{
        organization_id: organization.id,
        name: "",
        token_hash: "abc123"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).name
    end

    test "invalid changeset with name too short", %{organization: organization} do
      attrs = %{
        organization_id: organization.id,
        name: "",
        token_hash: "abc123"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      refute changeset.valid?
    end

    test "invalid changeset with name too long", %{organization: organization} do
      long_name = String.duplicate("a", 256)

      attrs = %{
        organization_id: organization.id,
        name: long_name,
        token_hash: "abc123"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      refute changeset.valid?
      assert "should be at most 255 character(s)" in errors_on(changeset).name
    end

    test "changeset with maximum valid name length", %{organization: organization} do
      max_name = String.duplicate("a", 255)

      attrs = %{
        organization_id: organization.id,
        name: max_name,
        token_hash: "abc123"
      }

      changeset = ApiToken.changeset(%ApiToken{}, attrs)
      assert changeset.valid?
    end
  end
end
