package models

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/acarl005/stripansi"
	"github.com/rs/zerolog"
)

type ArgoWatch struct {
	Name      string
	Namespace string
	Status    string
	Conditions
	Created  string
	Started  string
	Duration string
	Progress string
	Logs     []string
}

type Conditions struct {
	PodRunning bool
	Completed  bool
}

func (a *ArgoWatch) Equals(arg *ArgoWatch) bool {
	if arg == nil {
		return false
	}
	return a.Status == arg.Status && a.Progress == arg.Progress && a.Conditions.PodRunning == arg.Conditions.PodRunning && a.Conditions.Completed == arg.Conditions.Completed
}

func NewArgoLogs(name string, namespace string, stepMax int) *ArgoLogs {
	return &ArgoLogs{
		Name:        "oc-monitor-" + name,
		Namespace:   namespace,
		CreatedDate: time.Now().Format("2006-01-02 15:04:05"),
		StepCount:   0,
		StepMax:     stepMax,
		stop:        false,
		Seen:        []string{},
	}
}

type ArgoLogs struct {
	Name        string
	Namespace   string
	CreatedDate string
	StepCount   int
	StepMax     int
	stop        bool
	Started     time.Time
	Seen        []string
	Logs        []string
	IsStreaming bool
}

func (a *ArgoLogs) NewWatch() *ArgoWatch {
	return &ArgoWatch{
		Name:      a.Name,
		Namespace: a.Namespace,
		Status:    "Pending",
		Created:   a.CreatedDate,
		Started:   a.Started.Format("2006-01-02 15:04:05"),
		Conditions: Conditions{
			PodRunning: a.StepCount > 0 && a.StepCount < a.StepMax,
			Completed:  a.StepCount == a.StepMax,
		},
		Progress: fmt.Sprintf("%v/%v", a.StepCount, a.StepMax),
		Duration: "0s",
		Logs:     []string{},
	}

}

func (a *ArgoLogs) StartStepRecording(current_watch *ArgoWatch, logger zerolog.Logger) {
	jsonified, _ := json.Marshal(current_watch)
	logger.Info().Msg(string(jsonified))
	a.StepCount += 1
	a.Started = time.Now()
}

func (a *ArgoLogs) StopStepRecording(current *ArgoWatch) *ArgoWatch {
	fn := strings.Split(a.Name, "_")
	logs := []string{}
	err := false
	end := ""
	for _, input := range current.Logs {
		line := strings.TrimSpace(input)
		if line == "" || !strings.Contains(line, fn[0]) || !strings.Contains(line, ":") {
			continue
		}
		step := strings.Split(line, ":")
		if strings.Contains(line, "sub-process exited") {
			b := strings.Split(line, "time=\"")
			if len(b) > 1 {
				end = b[1][:19]
			}
		}
		if len(step) < 2 || strings.Contains(line, "time=") || strings.TrimSpace(strings.Join(step[1:], " : ")) == "" || strings.TrimSpace(strings.Join(step[1:], " : ")) == a.Name {
			continue
		}
		log := stripansi.Strip(strings.TrimSpace(strings.Join(step[1:], " : ")))
		t, e := strconv.Unquote(log)
		if e == nil {
			logs = append(logs, t)
		} else {
			logs = append(logs, strings.ReplaceAll(log, "\"", "`"))
		}

		if strings.Contains(logs[len(logs)-1], "Error") {
			err = true
		}
	}
	status := "Pending"
	if a.StepCount > 0 {
		status = "Running"
	}
	if a.StepCount == a.StepMax {
		if err {
			status = "Failed"
		} else {
			status = "Succeeded"
		}
	}
	duration := float64(0)
	if end != "" {
		timeE, _ := time.Parse("2006-01-02T15:04:05", end)
		duration = timeE.Sub(a.Started).Seconds()
	}
	current.Conditions = Conditions{
		PodRunning: a.StepCount > 0 && a.StepCount < a.StepMax,
		Completed:  a.StepCount == a.StepMax,
	}
	current.Progress = fmt.Sprintf("%v/%v", a.StepCount, a.StepMax)
	current.Duration = fmt.Sprintf("%v", fmt.Sprintf("%.2f", duration)+"s")

	current.Status = status
	return current
}