package server

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

	"code.justin.tv/creator-collab/log/errors"
	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
	timestamppb "google.golang.org/protobuf/types/known/timestamppb"
)

type fieldsMap map[string]string

func resultFieldsToMap(fields []*cloudwatchlogs.ResultField) fieldsMap {
	m := make(map[string]string, len(fields))

	for _, field := range fields {
		if field.Field == nil || field.Value == nil {
			continue
		}
		m[*field.Field] = *field.Value
	}

	return m
}

func (f fieldsMap) getUnixNanoAsTimestamp(fieldName string) (*timestamppb.Timestamp, error) {
	str, err := f.getStringField(fieldName)
	if err != nil {
		return nil, err
	}

	secAndNSec, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return nil, errors.Wrap(err, "")
	}
	sec := secAndNSec / 1000
	nsec := secAndNSec % 1000
	t := time.Unix(sec, nsec)

	return timestamppb.New(t), nil
}

func (f fieldsMap) getTextAsTimestamp(fieldName string) (*timestamppb.Timestamp, error) {
	str, err := f.getStringField(fieldName)
	if err != nil {
		return nil, err
	}

	t, err := time.Parse(time.RFC3339, str)
	if err != nil {
		return nil, errors.Wrap(err, "parsing time string failed")
	}

	return timestamppb.New(t), nil
}

func (f fieldsMap) getInt32(fieldName string) (int32, error) {
	str, err := f.getStringField(fieldName)
	if err != nil {
		return 0, err
	}

	intVal, err := strconv.ParseInt(str, 10, 32)
	if err != nil {
		return 0, errors.New("could not convert string field to a 32 bit int", errors.Fields{
			"field_name":  fieldName,
			"field_value": str,
		})
	}

	return int32(intVal), nil
}

func (f fieldsMap) getStringField(fieldName string) (string, error) {
	str, ok := f[fieldName]
	if !ok {
		return "", errors.New("fieldsMap did not contain field", errors.Fields{
			"field_name": fieldName,
		})
	}
	return str, nil
}

func (f fieldsMap) getOptionalStringField(fieldName string, defaultValue string) string {
	str, ok := f[fieldName]
	if !ok {
		return defaultValue
	}
	return str
}

func (f fieldsMap) String() string {
	buff, _ := json.MarshalIndent(f, "", "    ")
	return string(buff)
}
