package github

import (
	"fmt"
	"strconv"

	"github.com/tidbcloud/devops/api"
	githubapi "github.com/tidbcloud/devops/api/github"
	gitent "github.com/tidbcloud/devops/entity/github"
	ctrl "github.com/tidbcloud/devops/pkg/controller"
	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
	ghsvc "github.com/tidbcloud/devops/pkg/service/github"

	"github.com/gin-gonic/gin"
)

// ListPullRequests
//
//	@Id				GithubControllerListPullRequests
//	@Description	list pull requests.
//	@Tags			GithubController
//	@Accept			json
//	@Produce		json
//	@Param			req	query		githubapi.ListPullRequestsReq	false	"request param"
//	@Success		200	{object}	githubapi.ListPullRequestsResp
//	@Router			/api/v1/devops/github/pulls [get]
func (c *GithubController) ListPullRequests(ctx *gin.Context) {
	req := &githubapi.ListPullRequestsReq{}
	err := ctx.ShouldBindQuery(req)
	if err != nil {
		ctrl.FailWithCode(ctx, err, api.ErrCodeInvalidArgument)
		return
	}

	param := buildParamToListPR(req)
	prs, total, err := c.svc.ListPullRequests(ctx, param)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := githubapi.ListPullRequestsResp{
		Total: total,
		PRs:   prs,
	}

	ctrl.Success(ctx, resp)
}

// GetPullRequest
//
//	@Id				GithubControllerGetPullRequest
//	@Description	get a pull request.
//	@Tags			GithubController
//	@Accept			json
//	@Produce		json
//	@Param			owner		path		string	true	"owner name"
//	@Param			repo		path		string	true	"repo name"
//	@Param			pr_number	path		int		true	"pr number"
//	@Success		200			{object}	githubapi.GetPullRequestResp
//	@Router			/api/v1/devops/github/pulls/{owner}/{repo}/{pr_number} [get]
func (c *GithubController) GetPullRequest(ctx *gin.Context) {
	owner := ctx.Param("owner")
	repo := ctx.Param("repo")
	if owner == "" || repo == "" {
		ctrl.FailWithCode(ctx, fmt.Errorf("owner and repo are required"), api.ErrCodeInvalidArgument)
		return
	}

	prNumber, err := strconv.Atoi(ctx.Param("pr_number"))
	if err != nil {
		ctrl.FailWithCode(ctx, fmt.Errorf("pr_number is invalid"), api.ErrCodeInvalidArgument)
	}

	loc := gitent.NewPRLocation(owner, repo, int64(prNumber))
	pr, err := c.svc.GetPullRequestByLoc(ctx, loc)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	resp := githubapi.GetPullRequestResp{
		PR: *pr,
	}
	ctrl.Success(ctx, resp)
}

// SyncPullRequests
//
//	@Id				GithubControllerSyncPullRequests
//	@Description	sync all pull requests manually
//	@Tags			GithubController
//	@Accept			json
//	@Produce		json
//	@Success		200	{object}	api.BaseResp
//	@Router			/api/v1/devops-internal/github/pulls/sync [post]
func (c *GithubController) SyncPullRequests(ctx *gin.Context) {
	err := c.svc.SyncPullRequests(ctx)
	if err != nil {
		ctrl.Fail(ctx, err)
		return
	}

	ctrl.Success(ctx, nil)
}

func buildParamToListPR(req *githubapi.ListPullRequestsReq) ghsvc.ListPullRequestsParam {
	param := ghsvc.ListPullRequestsParam{
		Page:    int(req.Page),
		PerPage: int(req.PerPage),
	}
	if req.RepoLocation != nil {
		param.RepoLocation = pointer.Pointer(gitent.RepoLocation(*req.RepoLocation))
	}
	if len(req.PRLocations) != 0 {
		for _, loc := range req.PRLocations {
			param.PRLocations = append(param.PRLocations, gitent.PRLocation(loc))
		}
	}

	return param
}
