// Copyright 2019 Drone IO, Inc.
//
// Licensed 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 manager

import (
	"context"
	"encoding/json"

	"github.com/drone/drone/core"

	"github.com/sirupsen/logrus"
)

type updater struct {
	Builds  core.BuildStore
	Events  core.Pubsub
	Repos   core.RepositoryStore
	Steps   core.StepStore
	Stages  core.StageStore
	Webhook core.WebhookSender
}

func (u *updater) do(ctx context.Context, step *core.Step) error {
	logger := logrus.WithFields(
		logrus.Fields{
			"step.status": step.Status,
			"step.name":   step.Name,
			"step.id":     step.ID,
		},
	)

	if len(step.Error) > 500 {
		step.Error = step.Error[:500]
	}
	err := u.Steps.Update(noContext, step)
	if err != nil {
		logger.WithError(err).Warnln("manager: cannot update step")
		return err
	}

	stage, err := u.Stages.Find(noContext, step.StageID)
	if err != nil {
		logger.WithError(err).Warnln("manager: cannot find stage")
		return nil
	}

	build, err := u.Builds.Find(noContext, stage.BuildID)
	if err != nil {
		logger.WithError(err).Warnln("manager: cannot find build")
		return nil
	}

	repo, err := u.Repos.Find(noContext, build.RepoID)
	if err != nil {
		logger.WithError(err).Warnln("manager: cannot find repo")
		return nil
	}

	stages, err := u.Stages.ListSteps(noContext, build.ID)
	if err != nil {
		logger.WithError(err).Warnln("manager: cannot list stages")
		return nil
	}

	repo.Build = build
	repo.Build.Stages = stages
	data, _ := json.Marshal(repo)
	err = u.Events.Publish(noContext, &core.Message{
		Repository: repo.Slug,
		Visibility: repo.Visibility,
		Data:       data,
	})
	if err != nil {
		logger.WithError(err).Warnln("manager: cannot publish build event")
	}

	payload := &core.WebhookData{
		Event:  core.WebhookEventBuild,
		Action: core.WebhookActionUpdated,
		Repo:   repo,
		Build:  build,
	}
	err = u.Webhook.Send(noContext, payload)
	if err != nil {
		logger.WithError(err).Warnln("manager: cannot send global webhook")
	}
	return nil
}
