package manifest

import (
	"context"
	"time"

	aclient "github.com/akash-network/akash-api/go/node/client/v1beta2"
	"github.com/boz/go-lifecycle"
	sdk "github.com/cosmos/cosmos-sdk/types"

	"github.com/tendermint/tendermint/libs/log"

	dtypes "github.com/akash-network/akash-api/go/node/deployment/v1beta3"
	types "github.com/akash-network/akash-api/go/node/market/v1beta4"
	"github.com/akash-network/node/util/runner"

	"github.com/akash-network/provider/session"
)

type watchdog struct {
	leaseID types.LeaseID
	timeout time.Duration
	lc      lifecycle.Lifecycle
	sess    session.Session
	ctx     context.Context
	log     log.Logger
}

func newWatchdog(sess session.Session, parent <-chan struct{}, done chan<- dtypes.DeploymentID, leaseID types.LeaseID, timeout time.Duration) *watchdog {
	ctx, cancel := context.WithCancel(context.Background())
	result := &watchdog{
		leaseID: leaseID,
		timeout: timeout,
		lc:      lifecycle.New(),
		sess:    sess,
		ctx:     ctx,
		log:     sess.Log().With("leaseID", leaseID),
	}

	go func() {
		result.lc.WatchChannel(parent)
		cancel()
	}()

	go func() {
		<-result.lc.Done()
		done <- leaseID.DeploymentID()
	}()

	go result.run()

	return result
}

func (wd *watchdog) stop() {
	wd.lc.ShutdownAsync(nil)
}

func (wd *watchdog) run() {
	defer wd.lc.ShutdownCompleted()

	var runch <-chan runner.Result
	var err error

	wd.log.Debug("watchdog start")
	select {
	case <-time.After(wd.timeout):
		// Close the bid, since if this point is reached then a manifest has not been received
		wd.log.Info("watchdog closing bid")

		runch = runner.Do(func() runner.Result {
			msg := &types.MsgCloseBid{
				BidID: types.MakeBidID(wd.leaseID.OrderID(), wd.sess.Provider().Address()),
			}

			return runner.NewResult(wd.sess.Client().Tx().Broadcast(wd.ctx, []sdk.Msg{msg}, aclient.WithResultCodeAsError()))
		})
	case err = <-wd.lc.ShutdownRequest():
	}

	wd.lc.ShutdownInitiated(err)
	if runch != nil {
		result := <-runch
		if err := result.Error(); err != nil {
			wd.log.Error("failed closing bid", "err", err)
		}
	}
}
