/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tasks

import (
	"encoding/json"
	"github.com/apache/incubator-devlake/errors"
	"github.com/apache/incubator-devlake/plugins/core"
	"github.com/apache/incubator-devlake/plugins/github/models"
	"github.com/apache/incubator-devlake/plugins/helper"
)

var ExtractApiCommitsMeta = core.SubTaskMeta{
	Name:             "extractApiCommits",
	EntryPoint:       ExtractApiCommits,
	EnabledByDefault: false,
	Description:      "Extract raw commit data into tool layer table github_commits",
	DomainTypes:      []string{core.DOMAIN_TYPE_CODE},
}

type CommitsResponse struct {
	Sha       string `json:"sha"`
	Commit    Commit
	Url       string
	Author    *models.GithubAccount
	Committer *models.GithubAccount
}

type Commit struct {
	Author struct {
		Name  string
		Email string
		Date  helper.Iso8601Time
	}
	Committer struct {
		Name  string
		Email string
		Date  helper.Iso8601Time
	}
	Message string
}

func ExtractApiCommits(taskCtx core.SubTaskContext) errors.Error {
	data := taskCtx.GetData().(*GithubTaskData)

	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
			Ctx: taskCtx,
			/*
				This struct will be JSONEncoded and stored into database along with raw data itself, to identity minimal
				set of data to be process, for example, we process JiraCommits by Board
			*/
			Params: GithubApiParams{
				ConnectionId: data.Options.ConnectionId,
				Owner:        data.Options.Owner,
				Repo:         data.Options.Repo,
			},
			/*
				Table store raw data
			*/
			Table: RAW_COMMIT_TABLE,
		},
		Extract: func(row *helper.RawData) ([]interface{}, errors.Error) {
			commit := &CommitsResponse{}
			err := errors.Convert(json.Unmarshal(row.Data, commit))
			if err != nil {
				return nil, err
			}
			if commit.Sha == "" {
				return nil, nil
			}

			results := make([]interface{}, 0, 4)

			githubCommit := &models.GithubCommit{
				Sha:            commit.Sha,
				Message:        commit.Commit.Message,
				AuthorName:     commit.Commit.Author.Name,
				AuthorEmail:    commit.Commit.Author.Email,
				AuthoredDate:   commit.Commit.Author.Date.ToTime(),
				CommitterName:  commit.Commit.Committer.Name,
				CommitterEmail: commit.Commit.Committer.Email,
				CommittedDate:  commit.Commit.Committer.Date.ToTime(),
				Url:            commit.Url,
			}
			if commit.Author != nil {
				githubCommit.AuthorId = commit.Author.Id
				results = append(results, commit.Author)
			}
			if commit.Committer != nil {
				githubCommit.CommitterId = commit.Committer.Id
				results = append(results, commit.Committer)
			}

			githubRepoCommit := &models.GithubRepoCommit{
				ConnectionId: data.Options.ConnectionId,
				RepoId:       data.Repo.GithubId,
				CommitSha:    commit.Sha,
			}

			results = append(results, githubCommit)
			results = append(results, githubRepoCommit)
			return results, nil
		},
	})

	if err != nil {
		return err
	}

	return extractor.Execute()
}
