// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Drone Non-Commercial License
// that can be found in the LICENSE file.

// +build !oss

package crons

import (
	"context"
	"fmt"
	"net/http"

	"github.com/drone/drone/core"
	"github.com/drone/drone/handler/api/render"
	"github.com/sirupsen/logrus"

	"github.com/go-chi/chi"
)

// HandleExec returns an http.HandlerFunc that processes http
// requests to execute a cronjob on-demand.
func HandleExec(
	users core.UserStore,
	repos core.RepositoryStore,
	crons core.CronStore,
	commits core.CommitService,
	trigger core.Triggerer,
) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var (
			ctx       = r.Context()
			namespace = chi.URLParam(r, "owner")
			name      = chi.URLParam(r, "name")
			cron      = chi.URLParam(r, "cron")
		)

		repo, err := repos.FindName(ctx, namespace, name)
		if err != nil {
			render.NotFound(w, err)
			return
		}

		cronjob, err := crons.FindName(ctx, repo.ID, cron)
		if err != nil {
			render.NotFound(w, err)
			logger := logrus.WithError(err)
			logger.Debugln("api: cannot find cron")
			return
		}

		user, err := users.Find(ctx, repo.UserID)
		if err != nil {
			logger := logrus.WithError(err)
			logger.Debugln("api: cannot find repository owner")
			render.NotFound(w, err)
			return
		}

		commit, err := commits.FindRef(ctx, user, repo.Slug, cronjob.Branch)
		if err != nil {
			logger := logrus.WithError(err).
				WithField("namespace", repo.Namespace).
				WithField("name", repo.Name).
				WithField("cron", cronjob.Name)
			logger.Debugln("api: cannot find commit")
			render.NotFound(w, err)
			return
		}

		hook := &core.Hook{
			Trigger:      core.TriggerCron,
			Event:        core.EventCron,
			Link:         commit.Link,
			Timestamp:    commit.Author.Date,
			Message:      commit.Message,
			After:        commit.Sha,
			Ref:          fmt.Sprintf("refs/heads/%s", cronjob.Branch),
			Target:       cronjob.Branch,
			Author:       commit.Author.Login,
			AuthorName:   commit.Author.Name,
			AuthorEmail:  commit.Author.Email,
			AuthorAvatar: commit.Author.Avatar,
			Cron:         cronjob.Name,
			Sender:       commit.Author.Login,
		}

		build, err := trigger.Trigger(context.Background(), repo, hook)
		if err != nil {
			logger := logrus.WithError(err).
				WithField("namespace", repo.Namespace).
				WithField("name", repo.Name).
				WithField("cron", cronjob.Name)
			logger.Debugln("api: cannot trigger cron")
			render.InternalError(w, err)
			return
		}

		render.JSON(w, build, 200)
	}
}
