// TestListWorkItemLinkTypeOK tests if we can find the work item link types
// "test-bug-blocker" and "test-related" in the list of work item link types
func (s *workItemLinkTypeSuite) TestListWorkItemLinkTypeOK() {
	bugBlockerPayload := s.createDemoLinkType("test-bug-blocker")
	_, bugBlockerType := test.CreateWorkItemLinkTypeCreated(s.T(), nil, nil, s.linkTypeCtrl, bugBlockerPayload)
	require.NotNil(s.T(), bugBlockerType)

	relatedPayload := CreateWorkItemLinkType("test-related", workitem.SystemBug, workitem.SystemBug, bugBlockerType.Data.Relationships.LinkCategory.Data.ID)
	_, relatedType := test.CreateWorkItemLinkTypeCreated(s.T(), nil, nil, s.linkTypeCtrl, relatedPayload)
	require.NotNil(s.T(), relatedType)

	// Fetch a single work item link type
	_, linkTypeCollection := test.ListWorkItemLinkTypeOK(s.T(), nil, nil, s.linkTypeCtrl)
	require.NotNil(s.T(), linkTypeCollection)
	require.Nil(s.T(), linkTypeCollection.Validate())
	// Check the number of found work item link types
	require.NotNil(s.T(), linkTypeCollection.Data)
	require.Condition(s.T(), func() bool {
		return (len(linkTypeCollection.Data) >= 2)
	}, "At least two work item link types must exist (bug-blocker and related), but only %d exist.", len(linkTypeCollection.Data))
	// Search for the work item types that must exist at minimum
	toBeFound := 2
	for i := 0; i < len(linkTypeCollection.Data) && toBeFound > 0; i++ {
		if *linkTypeCollection.Data[i].Attributes.Name == "test-bug-blocker" || *linkTypeCollection.Data[i].Attributes.Name == "test-related" {
			s.T().Log("Found work item link type in collection: ", *linkTypeCollection.Data[i].Attributes.Name)
			toBeFound--
		}
	}
	require.Exactly(s.T(), 0, toBeFound, "Not all required work item link types (bug-blocker and related) where found.")

	// Check that the link categories are included in the response in the "included" array
	require.Len(s.T(), linkTypeCollection.Included, 1, "The work item link type should include it's work item link category.")
	categoryData, ok := linkTypeCollection.Included[0].(*app.WorkItemLinkCategoryData)
	require.True(s.T(), ok)
	require.Equal(s.T(), "test-user", *categoryData.Attributes.Name, "The work item link type's category should have the name 'test-user'.")
}
// TestListSourceAndTargetLinkTypes tests if we can find the work item link
// types for a given WIT.
func (s *workItemTypeSuite) TestListSourceAndTargetLinkTypes() {
	defer cleaner.DeleteCreatedEntities(s.DB)()

	// Create the work item type first and try to read it back in
	_, witAnimal := s.createWorkItemTypeAnimal()
	require.NotNil(s.T(), witAnimal)
	_, witPerson := s.createWorkItemTypePerson()
	require.NotNil(s.T(), witPerson)

	// Create work item link category
	linkCatPayload := CreateWorkItemLinkCategory("some-link-category")
	_, linkCat := test.CreateWorkItemLinkCategoryCreated(s.T(), nil, nil, s.linkCatCtrl, linkCatPayload)
	require.NotNil(s.T(), linkCat)

	// Create work item link type
	animalLinksToBugStr := "animal-links-to-bug"
	linkTypePayload := CreateWorkItemLinkType(animalLinksToBugStr, "animal", workitem.SystemBug, *linkCat.Data.ID)
	_, linkType := test.CreateWorkItemLinkTypeCreated(s.T(), nil, nil, s.linkTypeCtrl, linkTypePayload)
	require.NotNil(s.T(), linkType)

	// Create another work item link type
	bugLinksToAnimalStr := "bug-links-to-animal"
	linkTypePayload = CreateWorkItemLinkType(bugLinksToAnimalStr, workitem.SystemBug, "animal", *linkCat.Data.ID)
	_, linkType = test.CreateWorkItemLinkTypeCreated(s.T(), nil, nil, s.linkTypeCtrl, linkTypePayload)
	require.NotNil(s.T(), linkType)

	// Fetch source link types
	_, wiltCollection := test.ListSourceLinkTypesWorkitemtypeOK(s.T(), nil, nil, s.typeCtrl, "animal")
	require.NotNil(s.T(), wiltCollection)
	assert.Nil(s.T(), wiltCollection.Validate())
	// Check the number of found work item link types
	require.Len(s.T(), wiltCollection.Data, 1)
	require.Equal(s.T(), animalLinksToBugStr, *wiltCollection.Data[0].Attributes.Name)

	// Fetch target link types
	_, wiltCollection = test.ListTargetLinkTypesWorkitemtypeOK(s.T(), nil, nil, s.typeCtrl, "animal")
	require.NotNil(s.T(), wiltCollection)
	require.Nil(s.T(), wiltCollection.Validate())
	// Check the number of found work item link types
	require.Len(s.T(), wiltCollection.Data, 1)
	require.Equal(s.T(), bugLinksToAnimalStr, *wiltCollection.Data[0].Attributes.Name)
}
// The SetupTest method will be run before every test in the suite.
// SetupTest ensures that none of the work item links that we will create already exist.
// It will also make sure that some resources that we rely on do exists.
func (s *workItemLinkSuite) SetupTest() {
	s.cleanup()

	var err error

	// Create 3 work items (bug1, bug2, and feature1)
	bug1Payload := CreateWorkItem(workitem.SystemBug, "bug1")
	_, bug1 := test.CreateWorkitemCreated(s.T(), s.workItemSvc.Context, s.workItemSvc, s.workItemCtrl, bug1Payload)
	require.NotNil(s.T(), bug1)
	s.deleteWorkItems = append(s.deleteWorkItems, *bug1.Data.ID)
	s.bug1ID, err = strconv.ParseUint(*bug1.Data.ID, 10, 64)
	require.Nil(s.T(), err)
	fmt.Printf("Created bug1 with ID: %s\n", *bug1.Data.ID)

	bug2Payload := CreateWorkItem(workitem.SystemBug, "bug2")
	_, bug2 := test.CreateWorkitemCreated(s.T(), s.workItemSvc.Context, s.workItemSvc, s.workItemCtrl, bug2Payload)
	require.NotNil(s.T(), bug2)
	s.deleteWorkItems = append(s.deleteWorkItems, *bug2.Data.ID)
	s.bug2ID, err = strconv.ParseUint(*bug2.Data.ID, 10, 64)
	require.Nil(s.T(), err)
	fmt.Printf("Created bug2 with ID: %s\n", *bug2.Data.ID)

	bug3Payload := CreateWorkItem(workitem.SystemBug, "bug3")
	_, bug3 := test.CreateWorkitemCreated(s.T(), s.workItemSvc.Context, s.workItemSvc, s.workItemCtrl, bug3Payload)
	require.NotNil(s.T(), bug3)
	s.deleteWorkItems = append(s.deleteWorkItems, *bug3.Data.ID)
	s.bug3ID, err = strconv.ParseUint(*bug3.Data.ID, 10, 64)
	require.Nil(s.T(), err)
	fmt.Printf("Created bug3 with ID: %s\n", *bug3.Data.ID)

	feature1Payload := CreateWorkItem(workitem.SystemFeature, "feature1")
	_, feature1 := test.CreateWorkitemCreated(s.T(), s.workItemSvc.Context, s.workItemSvc, s.workItemCtrl, feature1Payload)
	require.NotNil(s.T(), feature1)
	s.deleteWorkItems = append(s.deleteWorkItems, *feature1.Data.ID)
	s.feature1ID, err = strconv.ParseUint(*feature1.Data.ID, 10, 64)
	require.Nil(s.T(), err)
	fmt.Printf("Created feature with ID: %s\n", *feature1.Data.ID)

	// Create a work item link category
	createLinkCategoryPayload := CreateWorkItemLinkCategory("test-user")
	_, workItemLinkCategory := test.CreateWorkItemLinkCategoryCreated(s.T(), nil, nil, s.workItemLinkCategoryCtrl, createLinkCategoryPayload)
	require.NotNil(s.T(), workItemLinkCategory)
	//s.deleteWorkItemLinkCategories = append(s.deleteWorkItemLinkCategories, *workItemLinkCategory.Data.ID)
	s.userLinkCategoryID = *workItemLinkCategory.Data.ID
	fmt.Printf("Created link category with ID: %s\n", *workItemLinkCategory.Data.ID)

	// Create work item link type payload
	createLinkTypePayload := CreateWorkItemLinkType("test-bug-blocker", workitem.SystemBug, workitem.SystemBug, s.userLinkCategoryID)
	_, workItemLinkType := test.CreateWorkItemLinkTypeCreated(s.T(), nil, nil, s.workItemLinkTypeCtrl, createLinkTypePayload)
	require.NotNil(s.T(), workItemLinkType)
	//s.deleteWorkItemLinkTypes = append(s.deleteWorkItemLinkTypes, *workItemLinkType.Data.ID)
	s.bugBlockerLinkTypeID = *workItemLinkType.Data.ID
	fmt.Printf("Created link type with ID: %s\n", *workItemLinkType.Data.ID)
}
// TestCreateWorkItemLinkType tests if we can create the "test-bug-blocker" work item link type
func (s *workItemLinkTypeSuite) TestCreateAndDeleteWorkItemLinkType() {
	createPayload := s.createDemoLinkType("test-bug-blocker")
	_, workItemLinkType := test.CreateWorkItemLinkTypeCreated(s.T(), nil, nil, s.linkTypeCtrl, createPayload)
	require.NotNil(s.T(), workItemLinkType)
	// Check that the link category is included in the response in the "included" array
	require.Len(s.T(), workItemLinkType.Included, 1, "The work item link type should include it's work item link category.")
	categoryData, ok := workItemLinkType.Included[0].(*app.WorkItemLinkCategoryData)
	require.True(s.T(), ok)
	require.Equal(s.T(), "test-user", *categoryData.Attributes.Name, "The work item link type's category should have the name 'test-user'.")
	_ = test.DeleteWorkItemLinkTypeOK(s.T(), nil, nil, s.linkTypeCtrl, *workItemLinkType.Data.ID)
}
// TestShowWorkItemLinkTypeOK tests if we can fetch the "system" work item link type
func (s *workItemLinkTypeSuite) TestShowWorkItemLinkTypeOK() {
	// Create the work item link type first and try to read it back in
	createPayload := s.createDemoLinkType("test-bug-blocker")
	_, workItemLinkType := test.CreateWorkItemLinkTypeCreated(s.T(), nil, nil, s.linkTypeCtrl, createPayload)
	require.NotNil(s.T(), workItemLinkType)
	_, readIn := test.ShowWorkItemLinkTypeOK(s.T(), nil, nil, s.linkTypeCtrl, *workItemLinkType.Data.ID)
	require.NotNil(s.T(), readIn)
	// Convert to model space and use equal function
	expected := link.WorkItemLinkType{}
	actual := link.WorkItemLinkType{}
	require.Nil(s.T(), link.ConvertLinkTypeToModel(*workItemLinkType, &expected))
	require.Nil(s.T(), link.ConvertLinkTypeToModel(*readIn, &actual))
	require.True(s.T(), expected.Equal(actual))
	// Check that the link category is included in the response in the "included" array
	require.Len(s.T(), readIn.Included, 1, "The work item link type should include it's work item link category.")
	categoryData, ok := readIn.Included[0].(*app.WorkItemLinkCategoryData)
	require.True(s.T(), ok)
	require.Equal(s.T(), "test-user", *categoryData.Attributes.Name, "The work item link type's category should have the name 'test-user'.")
	require.NotNil(s.T(), readIn.Data.Links, "The link type MUST include a self link")
	require.NotEmpty(s.T(), readIn.Data.Links.Self, "The link type MUST include a self link that's not empty")
}
func (s *workItemLinkTypeSuite) TestUpdateWorkItemLinkTypeOK() {
	createPayload := s.createDemoLinkType("test-bug-blocker")
	_, workItemLinkType := test.CreateWorkItemLinkTypeCreated(s.T(), nil, nil, s.linkTypeCtrl, createPayload)
	require.NotNil(s.T(), workItemLinkType)
	// Specify new description for link type that we just created
	// Wrap data portion in an update payload instead of a create payload
	updateLinkTypePayload := &app.UpdateWorkItemLinkTypePayload{
		Data: workItemLinkType.Data,
	}
	newDescription := "Lalala this is a new description for the work item type"
	updateLinkTypePayload.Data.Attributes.Description = &newDescription
	_, lt := test.UpdateWorkItemLinkTypeOK(s.T(), nil, nil, s.linkTypeCtrl, *updateLinkTypePayload.Data.ID, updateLinkTypePayload)
	require.NotNil(s.T(), lt.Data)
	require.NotNil(s.T(), lt.Data.Attributes)
	require.NotNil(s.T(), lt.Data.Attributes.Description)
	require.Equal(s.T(), newDescription, *lt.Data.Attributes.Description)
	// Check that the link categories are included in the response in the "included" array
	require.Len(s.T(), lt.Included, 1, "The work item link type should include it's work item link category.")
	categoryData, ok := lt.Included[0].(*app.WorkItemLinkCategoryData)
	require.True(s.T(), ok)
	require.Equal(s.T(), "test-user", *categoryData.Attributes.Name, "The work item link type's category should have the name 'test-user'.")
}