defmodule Towerops.Sites.SiteTest do
  use Towerops.DataCase

  import Towerops.AccountsFixtures
  import Towerops.OrganizationsFixtures

  alias Towerops.Sites.Site

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

    test "valid changeset with required fields", %{organization: organization} do
      changeset =
        Site.changeset(%Site{}, %{
          name: "Test Site",
          organization_id: organization.id
        })

      assert changeset.valid?
    end

    test "valid changeset with all fields", %{organization: organization} do
      changeset =
        Site.changeset(%Site{}, %{
          name: "Test Site",
          description: "A test site",
          location: "123 Main St",
          organization_id: organization.id
        })

      assert changeset.valid?
    end

    test "invalid changeset without name", %{organization: organization} do
      changeset =
        Site.changeset(%Site{}, %{
          organization_id: organization.id
        })

      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).name
    end

    test "invalid changeset without organization_id" do
      changeset =
        Site.changeset(%Site{}, %{
          name: "Test Site"
        })

      refute changeset.valid?
      assert "can't be blank" in errors_on(changeset).organization_id
    end

    test "invalid changeset with short name", %{organization: organization} do
      changeset =
        Site.changeset(%Site{}, %{
          name: "A",
          organization_id: organization.id
        })

      refute changeset.valid?
      assert "should be at least 2 character(s)" in errors_on(changeset).name
    end

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

      changeset =
        Site.changeset(%Site{}, %{
          name: long_name,
          organization_id: organization.id
        })

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

    test "invalid changeset with long description", %{organization: organization} do
      long_description = String.duplicate("a", 1001)

      changeset =
        Site.changeset(%Site{}, %{
          name: "Test Site",
          description: long_description,
          organization_id: organization.id
        })

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

    test "invalid changeset with long location", %{organization: organization} do
      long_location = String.duplicate("a", 201)

      changeset =
        Site.changeset(%Site{}, %{
          name: "Test Site",
          location: long_location,
          organization_id: organization.id
        })

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

    test "valid changeset with parent site", %{organization: organization} do
      {:ok, parent_site} =
        Towerops.Sites.create_site(%{
          name: "Parent Site",
          organization_id: organization.id
        })

      changeset =
        Site.changeset(%Site{}, %{
          name: "Child Site",
          organization_id: organization.id,
          parent_site_id: parent_site.id
        })

      assert changeset.valid?
    end

    test "invalid changeset with circular parent reference", %{organization: organization} do
      {:ok, site} =
        Towerops.Sites.create_site(%{
          name: "Test Site",
          organization_id: organization.id
        })

      changeset =
        Site.changeset(site, %{
          parent_site_id: site.id
        })

      refute changeset.valid?
      assert "cannot be the same as the site itself" in errors_on(changeset).parent_site_id
    end

    test "changeset allows nil parent_site_id", %{organization: organization} do
      changeset =
        Site.changeset(%Site{}, %{
          name: "Test Site",
          organization_id: organization.id,
          parent_site_id: nil
        })

      assert changeset.valid?
    end
  end
end
