package pull

import (
	"context"
	"fmt"

	"code.gitea.io/gitea/models/db"
	gitea_issues_model "code.gitea.io/gitea/models/issues"
	gitea_repo_model "code.gitea.io/gitea/models/repo"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/timeutil"
	"xorm.io/xorm"
)

type PullRequestVersion struct {
	ID            int64                           `xorm:"pk autoincr"`
	RepoID        int64                           `xorm:"INDEX"`
	Repo          *gitea_repo_model.Repository    `xorm:"-"`
	PullID        int64                           `xorm:"INDEX"`
	Pull          *gitea_issues_model.PullRequest `xorm:"-"`
	AddLineNum    int
	CommitsCount  int
	DelLineNum    int
	FilesCount    int
	HeadCommitID  string             `xorm:"VARCHAR(40)"`
	BaseCommitID  string             `xorm:"VARCHAR(40)"`
	StartCommitID string             `xorm:"VARCHAR(40)"`
	CreatedUnix   timeutil.TimeStamp `xorm:"created INDEX"`
	UpdatedUnix   timeutil.TimeStamp `xorm:"updated INDEX"`
}

func listPullRequestVersionStatement(ctx context.Context, prID int64, opts *db.ListOptions) (*xorm.Session, error) {
	sess := db.GetEngine(db.DefaultContext).Where("pull_request_version.pull_id=?", prID)

	sess.Join("INNER", "repository", "pull_request_version.repo_id = repository.id")
	return sess, nil
}

func PullRequestVersions(ctx context.Context, prID int64, opts *db.ListOptions) ([]*PullRequestVersion, int64, error) {
	if opts.Page <= 0 {
		opts.Page = 1
	}

	countSession, err := listPullRequestVersionStatement(ctx, prID, opts)
	if err != nil {
		log.Error("listPullRequestVersionStatement: %v", err)
		return nil, 0, err
	}
	maxResults, err := countSession.Count(new(PullRequestVersion))
	if err != nil {
		log.Error("Count pull_request_versions: %v", err)
		return nil, maxResults, err
	}
	findSession, err := listPullRequestVersionStatement(ctx, prID, opts)
	if err != nil {
		log.Error("listPullRequestVersionStatement: %v", err)
		return nil, 0, err
	}
	findSession = db.SetSessionPagination(findSession, opts)
	prvs := make([]*PullRequestVersion, 0, opts.PageSize)
	return prvs, maxResults, findSession.Find(&prvs)
}

func GetPullRequestVersionByID(ctx context.Context, prID, id int64) (*PullRequestVersion, error) {
	if id < 1 {
		return nil, gitea_issues_model.ErrPullRequestNotExist{}
	}
	prv := &PullRequestVersion{
		PullID: prID,
		ID:     id,
	}

	has, err := db.GetEngine(ctx).Get(prv)
	if err != nil {
		return nil, err
	} else if !has {
		return nil, gitea_issues_model.ErrPullRequestNotExist{}
	}

	return prv, nil
}

// NewPullRequestDiff creates new pull request diff version for repository.
func NewPullRequestVersion(ctx context.Context, repo *gitea_repo_model.Repository, pr *gitea_issues_model.PullRequest, addLineNum, commitsCount, delLineNUm, filesCount int, headCommitID, baseCommitID, StartCommitID string) (err error) {
	var version PullRequestVersion
	version.PullID = pr.ID
	version.RepoID = repo.ID
	version.AddLineNum = addLineNum
	version.CommitsCount = commitsCount
	version.DelLineNum = delLineNUm
	version.FilesCount = filesCount
	version.HeadCommitID = headCommitID
	version.BaseCommitID = baseCommitID
	version.StartCommitID = StartCommitID
	if _, err = db.GetEngine(ctx).Insert(version); err != nil {
		return fmt.Errorf("insert pull version repo: %v", err)
	}

	return nil
}
