// Table driven tests for Flattening the Github response data without assignee
func TestFlattenGithubResponseMapWithoutAssignee(t *testing.T) {
	resource.Require(t, resource.UnitTest)

	// githubData struct define test file and test url
	type githubData struct {
		inputFile      string
		expectedOutput bool
		inputURL       string
	}

	// JSON data to test the issue mapping for github
	var gitData = []githubData{
		// Github data with assignee to map local workItem to remote workItem
		{"github_issue_with_assignee.json", true, "http://api.github.com/repos/almighty-test/almighty-test-unit/issues/2"},
		// Github data with labels and without assignee
		// assignee field is skipped if that is null
		{"github_issue_with_labels.json", true, "https://api.github.com/repos/almighty-test/almighty-test-unit/issues/3"},
		// The Github issue URL doesn't exist. So, the mapping will not happen
		// The map created from the Flatten will be empty
		{"github_issue_invalid.json", false, "https://api.github.com/repos/almighty-unit-test/almighty-test/issues/255"},
	}

	for _, j := range gitData {
		testString, err := test.LoadTestData(j.inputFile, func() ([]byte, error) {
			return provideRemoteData(j.inputURL)
		})
		require.Nil(t, err)

		var nestedMap map[string]interface{}
		err = json.Unmarshal(testString, &nestedMap)
		require.Nil(t, err, "Incorrect dataset %s", testString)

		OneLevelMap := Flatten(nestedMap)

		githubKeyMap := WorkItemKeyMaps[ProviderGithub]

		// Verifying if the new map is usable.
		for k := range githubKeyMap {
			_, ok := OneLevelMap[string(k.expression)]
			if k.expression == GithubAssignee {
				continue
			}
			assert.Equal(t, ok, j.expectedOutput, fmt.Sprintf("Could not access %s from the flattened map ", k))
		}
	}
}
// Table driven tests for Flattening the Github response data with assignee
func TestFlattenGithubResponseMap(t *testing.T) {
	resource.Require(t, resource.UnitTest)

	// githubData struct define test file and test url
	type githubData struct {
		inputFile      string
		expectedOutput bool
		inputURL       string
	}

	// JSON data to test the issue mapping for github
	var gitData = []githubData{
		// JSON data file of Github issue with assignee to test that the data
		// is getting correctly Mapped through the Map function
		// Github Issue API URL for the respective JSON data file to update the cache
		{"github_issue_with_assignee.json", true, "http://api.github.com/repos/almighty-test/almighty-test-unit/issues/2"},
		// Github issue with assignee and label
		{"github_issue_with_assignee_labels.json", true, "https://api.github.com/repos/almighty-unit-test/almighty-test/issues/1"},
		// The Github issue URL doesn't exist. So, the mapping will not happen
		// The map created from the Flatten will be empty
		{"github_issue_invalid.json", false, "https://api.github.com/repos/almighty-unit-test/almighty-test/issues/255"},
	}

	for _, j := range gitData {
		testString, err := test.LoadTestData(j.inputFile, func() ([]byte, error) {
			return provideRemoteData(j.inputURL)
		})
		require.Nil(t, err)

		var nestedMap map[string]interface{}
		err = json.Unmarshal(testString, &nestedMap)
		require.Nil(t, err, "Incorrect dataset %s", testString)

		OneLevelMap := Flatten(nestedMap)

		githubKeyMap := WorkItemKeyMaps[ProviderGithub]
		// Verifying if the new map is usable.
		for k := range githubKeyMap {
			_, ok := OneLevelMap[string(k.expression)]
			assert.Equal(t, ok, j.expectedOutput, fmt.Sprintf("Could not access %s from the flattened map ", k))
		}
	}
}
// Table driven tests for the Mapping of Github issues
func TestGitHubIssueMapping(t *testing.T) {
	resource.Require(t, resource.UnitTest)

	// githubData struct define test file and test url
	type githubData struct {
		inputFile      string
		expectedOutput bool
		inputURL       string
	}

	var gitData = []githubData{
		// JSON data file of Github issue with assignee to test that the data is getting correctly Mapped through the Map function
		// Github Issue API URL for the respective JSON data file to update the cache
		{"github_issue_with_assignee.json", true, "http://api.github.com/repos/almighty-test/almighty-test-unit/issues/2"},
		// JSON data file of Github issue with assignee and label
		// Issue API URL for the respective JSON file to update the cache
		{"github_issue_with_assignee_labels.json", true, "https://api.github.com/repos/almighty-unit-test/almighty-test/issues/1"},
	}

	for _, j := range gitData {
		content, err := test.LoadTestData(j.inputFile, func() ([]byte, error) {
			return provideRemoteData(j.inputURL)
		})
		require.Nil(t, err)

		workItemMap := WorkItemKeyMaps[ProviderGithub]
		remoteTrackerkItem := TrackerItem{Item: string(content[:]), RemoteItemID: "xyz", TrackerID: uint64(0)}

		remoteWorkItemImpl := RemoteWorkItemImplRegistry[ProviderGithub]
		gh, err := remoteWorkItemImpl(remoteTrackerkItem)
		require.Nil(t, err)

		workItem, err := Map(gh, workItemMap)
		require.Nil(t, err)

		for _, localWorkItemKey := range workItemMap {
			t.Log("Mapping ", localWorkItemKey)
			_, ok := workItem.Fields[localWorkItemKey]
			assert.Equal(t, ok, j.expectedOutput, fmt.Sprintf("%s not mapped", localWorkItemKey))
		}
	}
}
func TestFlattenJiraResponseMapWithoutAssignee(t *testing.T) {
	resource.Require(t, resource.UnitTest)

	// jiraData struct define test file and test url
	type jiraData struct {
		inputFile      string
		expectedOutput bool
		inputURL       string
	}

	// JSON data to test the issue mapping for jira
	var jir = []jiraData{
		// JSON data file of Jira issue with null assignee, test assertion, Issue API URL for the respective JSON file to update the cache
		{"jira_issue_without_assignee.json", true, "http://jira.atlassian.com/rest/api/latest/issue/JRA-10"},
		// JSON data file of Jira issue, test assertion, Issue API URL for the respective JSON file to update the cache
		{"jira_issue_mapping_data.json", true, "https://jira.atlassian.com/rest/api/latest/issue/JRA-3"},
	}

	for _, j := range jir {

		testString, err := test.LoadTestData(j.inputFile, func() ([]byte, error) {
			return provideRemoteData(j.inputURL)
		})
		require.Nil(t, err)

		var nestedMap map[string]interface{}
		err = json.Unmarshal(testString, &nestedMap)
		require.Nil(t, err, "Incorrect dataset %s", testString)

		OneLevelMap := Flatten(nestedMap)
		jiraKeyMap := WorkItemKeyMaps[ProviderJira]

		// Verifying if the newly converted map is usable.
		for k := range jiraKeyMap {
			_, ok := OneLevelMap[string(k.expression)]
			if k.expression == JiraAssignee {
				continue
			}
			assert.Equal(t, ok, j.expectedOutput, fmt.Sprintf("Could not access %s from the flattened map ", k))
		}
	}
}
// Table driven tests for the Mapping of Jira issues
func TestJiraIssueMapping(t *testing.T) {
	resource.Require(t, resource.UnitTest)

	// jiraData struct define test file and test url
	type jiraData struct {
		inputFile      string
		expectedOutput bool
		inputURL       string
	}
	// JSON data to test the issue mapping for jira
	var jir = []jiraData{
		// JSON data file of Jira issue with null assignee
		// Issue API URL for the respective JSON file to update the cache
		{"jira_issue_without_assignee.json", true, "http://jira.atlassian.com/rest/api/latest/issue/JRA-9"},
		// JSON data file of Jira issue
		// Issue API URL for the respective JSON file to update the cache
		{"jira_issue_mapping_data.json", true, "https://jira.atlassian.com/rest/api/latest/issue/JRA-3"},
	}

	for _, j := range jir {
		content, err := test.LoadTestData(j.inputFile, func() ([]byte, error) {
			return provideRemoteData(j.inputURL)
		})
		require.Nil(t, err)

		workItemMap := WorkItemKeyMaps[ProviderJira]
		remoteTrackerItem := TrackerItem{Item: string(content[:]), RemoteItemID: "xyz", TrackerID: uint64(0)}
		remoteWorkItemImpl := RemoteWorkItemImplRegistry[ProviderJira]
		ji, err := remoteWorkItemImpl(remoteTrackerItem)
		require.Nil(t, err)

		workItem, err := Map(ji, workItemMap)
		require.Nil(t, err)

		for _, localWorkItemKey := range workItemMap {
			t.Log("Mapping ", localWorkItemKey)
			_, ok := workItem.Fields[localWorkItemKey]
			assert.Equal(t, ok, j.expectedOutput, fmt.Sprintf("%s not mapped", localWorkItemKey))
		}
	}
}
func TestConvertGithubIssue(t *testing.T) {
	resource.Require(t, resource.Database)
	defer cleaner.DeleteCreatedEntities(db)()

	t.Log("Scenario 3 : Mapping and persisting a Github issue")

	tr := Tracker{URL: "https://api.github.com/", Type: ProviderGithub}

	db = db.Create(&tr)
	require.Nil(t, db.Error)

	tq := TrackerQuery{Query: "some random query", Schedule: "0 0 0 * * *", TrackerID: tr.ID}
	db.Create(&tq)

	models.Transactional(db, func(tx *gorm.DB) error {
		content, err := test.LoadTestData("github_issue_mapping.json", func() ([]byte, error) {
			return provideRemoteData(GitIssueWithAssignee)
		})
		if err != nil {
			t.Fatal(err)
		}

		remoteItemDataGithub := TrackerItemContent{
			Content: content[:],
			ID:      GitIssueWithAssignee, // GH issue url
		}

		workItemGithub, err := convert(tx, int(tq.ID), remoteItemDataGithub, ProviderGithub)

		assert.Nil(t, err)
		assert.Equal(t, "map flatten : test case : with assignee", workItemGithub.Fields[workitem.SystemTitle])
		assert.Equal(t, "sbose78", workItemGithub.Fields[workitem.SystemCreator])
		assert.Equal(t, "sbose78", workItemGithub.Fields[workitem.SystemAssignees].([]interface{})[0])
		assert.Equal(t, "open", workItemGithub.Fields[workitem.SystemState])

		return errors.WithStack(err)
	})

}