package middleware

import (
	"fmt"
	"sort"
	"time"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/schrodinger/notifiermgr/event"
	"github.com/pingcap/schrodinger/notifiermgr/util"
	"github.com/pingcap/schrodinger/pkg/storage"
	"github.com/pingcap/schrodinger/pkg/types"
	globalUtil "github.com/pingcap/schrodinger/util"
)

func dailyReport(configPtr *interface{}) Middleware {
	input := make(chan event.Event)
	output := make(chan event.Event)

	config, err := util.GetSimpleMap(configPtr)
	if err != nil {
		log.Errorf("Error while mapping a config to map: %s", errors.ErrorStack(err))
	}

	baseDomain := config.GetString("baseDomain")
	if baseDomain == nil {
		return nil
	}

	store, err := util.GetStorageFromConfig(configPtr)

	if err != nil {
		log.Errorf("Error while connecting storage: %s", errors.ErrorStack(err))
	}

	go func() {
		for range input {
			experiments, _ := store.ListExperimentProcess(&storage.ExperimentProcessConditions{
				Status:    []string{"ABNORMAL"},
				Destroyed: []string{"0"},
			})

			var unknownTimeExperiments []*types.ExperimentProcess
			groupedExperiments := make(map[int][]*types.ExperimentProcess)

			for _, ep := range experiments {
				endTime, err := time.Parse(globalUtil.TimeFormat, ep.Utime)
				if err != nil {
					log.Errorf("Error while parsing time %s", errors.ErrorStack(err))

					unknownTimeExperiments = append(unknownTimeExperiments, ep)
					continue
				}

				day := int(time.Now().Sub(endTime).Hours() / 24)

				list, ok := groupedExperiments[day]
				if !ok {
					groupedExperiments[day] = []*types.ExperimentProcess{ep}
				} else {
					groupedExperiments[day] = append(list, ep)
				}
			}

			var days []int
			for day := range groupedExperiments {
				days = append(days, day)
			}
			sort.Ints(days)

			reports := "Unhandled Experiments (grouped by NOW - UPDATE TIME):\n"
			for _, day := range days {
				eps := groupedExperiments[day]

				alertText := ""
				for _, ep := range eps {
					alertText += genSingleExperimentText(ep, *baseDomain) + "\n"
				}

				reports += fmt.Sprintf(singleDayReport, day, alertText)
			}

			if len(unknownTimeExperiments) > 0 {
				reports += "Unkown Day:\n"

				for _, ep := range unknownTimeExperiments {
					reports += genSingleExperimentText(ep, *baseDomain) + "\n"
				}
			}

			output <- Notification{
				Content: reports,
			}
		}
	}()

	return &RealMiddleware{
		input,
		output,
	}
}

func genSingleExperimentText(ep *types.ExperimentProcess, baseDomain string) string {
	return fmt.Sprintf(
		singleExperimentTemplate,
		ep.Creator, baseDomain, ep.BoxID, ep.ID, ep.BoxName, ep.Name,
	)
}

const singleExperimentTemplate = `@%s <https://%s/#/experimentdetail?boxid=%d&experimentid=%d|Box *%s* Experiment *%s*>`

const singleDayReport = `
%d Day:
%s
`
