package repo

import (
	"net/http"

	"code.gitea.io/gitea/modules/context"
	gitea_git "code.gitea.io/gitea/modules/git"
	hat_git "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/git"
	hat_api "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/structs"
)

type APIBlameResponse struct {
	FileSize    int64               `json:"file_size"`
	FileName    string              `json:"file_name"`
	NumberLines int                 `json:"num_lines"`
	BlameParts  []hat_api.BlamePart `json:"blame_parts"`
}

func GetRepoRefBlame(ctx *context.APIContext) {
	if ctx.Repo.Repository.IsEmpty {
		ctx.NotFound()
		return
	}

	var commit *gitea_git.Commit
	if sha := ctx.FormString("sha"); len(sha) > 0 {
		var err error
		commit, err = ctx.Repo.GitRepo.GetCommit(sha)
		if err != nil {
			if gitea_git.IsErrNotExist(err) {
				ctx.NotFound()
			} else {
				ctx.Error(http.StatusInternalServerError, "GetCommit", err)
			}
			return
		}
	}

	filepath := ctx.FormString("filepath")
	entry, err := commit.GetTreeEntryByPath(filepath)
	if err != nil {
		ctx.NotFoundOrServerError("commit.GetTreeEntryByPath", gitea_git.IsErrNotExist, err)
		return
	}

	blob := entry.Blob()
	numLines, err := blob.GetBlobLineCount()
	if err != nil {
		ctx.Error(http.StatusInternalServerError, "GetBlobLineCount", err)
		return
	}
	blameReader, err := hat_git.CreateBlameReader(ctx, ctx.Repo.Repository.RepoPath(), commit.ID.String(), filepath)
	if err != nil {
		ctx.Error(http.StatusInternalServerError, "CreateBlameReader", err)
		return
	}
	defer blameReader.Close()

	blameParts := make([]hat_api.BlamePart, 0)
	currentNumber := 1
	for {
		blamePart, err := blameReader.NextApiPart(ctx.Repo.GitRepo)
		if err != nil {
			ctx.Error(http.StatusInternalServerError, "NextApiPart", err)
			return
		}
		if blamePart == nil {
			break
		}
		blamePart.CurrentNumber = currentNumber
		blameParts = append(blameParts, *blamePart)
		currentNumber += blamePart.EffectLine
	}
	ctx.JSON(http.StatusOK, APIBlameResponse{
		FileSize:    blob.Size(),
		FileName:    blob.Name(),
		NumberLines: numLines,
		BlameParts:  blameParts,
	})
}
