package parser

import (
	"encoding/json"
	"time"

	"code.justin.tv/creator-collab/log/errors"

	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
	"github.com/google/uuid"
)

type QueryResult struct {
	AccountID string
	LogGroup  string
	LogStream string
	Message   string
	Timestamp string // E.g. "2006-01-02 15:04:05"
}

type CloudwatchLogsQueryResult []*cloudwatchlogs.ResultField

func ParseCloudWatchLogsInsightsQueryResult(queryResult *QueryResult) (*LogEvent, error) {
	timestamp, err := parseCloudWatchLogsInsightsTime(queryResult.Timestamp)
	if err != nil {
		return nil, err
	}

	msgProps, err := parseCloudWatchLogsInsightsMessage(queryResult.Message)
	if err != nil {
		return nil, err
	}

	idUUID, err := uuid.NewRandom()
	if err != nil {
		return nil, errors.Wrap(err, "could not generate log event ID")
	}
	logEventID := idUUID.String()

	return &LogEvent{
		AccountID:   queryResult.AccountID,
		Fields:      msgProps.fields,
		Fingerprint: msgProps.fingerprint,
		Level:       msgProps.level,
		LogEventID:  logEventID,
		LogGroup:    queryResult.LogGroup,
		LogStream:   queryResult.LogStream,
		Message:     msgProps.message,
		Operation:   msgProps.operation,
		Raw:         queryResult.Message,
		RequestID:   msgProps.requestID,
		StackTrace:  msgProps.stackTrace,
		Timestamp:   timestamp,
	}, nil
}

func parseCloudWatchLogsInsightsMessage(cwlMsg string) (*messageProperties, error) {
	jsonObj := make(map[string]interface{}, 0)
	err := json.Unmarshal([]byte(cwlMsg), &jsonObj)
	if err != nil {
		return parsePlainTextPayload(cwlMsg)
	}

	return parseJsonPayload(jsonObj)
}

func parseCloudWatchLogsInsightsTime(s string) (time.Time, error) {
	if s == "" {
		return time.Time{}, errors.New("empty time string")
	}

	t, err := time.Parse("2006-01-02 15:04:05", s)
	if err != nil {
		return time.Time{}, errors.Wrap(err, "parsing time failed", errors.Fields{
			"time": t,
		})
	}

	return t, err
}
