package watcher

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

	"github.com/pingcap/errors"
	tidbClusterV1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
	tidbClusterLabel "github.com/pingcap/tidb-operator/pkg/label"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/workqueue"

	"github.com/tidbcloud/billing-reporter/conf"
	"github.com/tidbcloud/billing-reporter/report"
	"github.com/tidbcloud/billing-reporter/scrape"
)

// TODO: fill the tenant Id and cluster Id from tc in tcr
func fillTenantIdAndClusterId(tcr *TidbClusterRef, tc *tidbClusterV1alpha1.TidbCluster) {}

func splitMetaNamespaceKey(key string) (string, string, error) {
	parts := strings.Split(key, "/")
	if len(parts) != 2 {
		return "", "", errors.Errorf("unexpected key format: %q", key)
	}
	return parts[0], parts[1], nil
}

func watchForPod(informer cache.SharedIndexInformer, q workqueue.Interface, startTime time.Time) {
	enqueueFn := func(obj interface{}, eventType string) {
		pod, ok := obj.(metav1.Object)
		if !ok {
			utilruntime.HandleError(errors.Errorf("%+v is not a Object, cannot get controller from it", obj))
			return
		}

		k := Key{
			Pod: pod,
		}
		// podWatcher only watch the pod event after it started timestamp
		switch eventType {
		case "add":
			if pod.GetCreationTimestamp().Time.Before(startTime) {
				return
			}
			k.Type = CreationEventType
			k.Timestamp = pod.GetCreationTimestamp().Unix()
		case "delete":
			if pod.GetDeletionTimestamp().Time.Before(startTime) {
				return
			}
			k.Type = DeletionEventType
			k.Timestamp = pod.GetDeletionTimestamp().Unix()
		default:
			return
		}

		// podWatcher only watch the tikv/tidb pod event managed by tidb-operator
		l := tidbClusterLabel.Label(pod.GetLabels())
		if !l.IsManagedByTiDBOperator() || (!l.IsTiKV() && !l.IsTiDB()) {
			return
		}

		key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
		if err != nil {
			utilruntime.HandleError(errors.Errorf("Cound't get key for pod %+v: %v", obj, err))
			return
		}
		k.MetaNamespaceKey = key
		q.Add(k)
	}

	deletionEnqueueFn := func(obj interface{}) {
		enqueueFn(obj, "delete")
	}
	addEnqueueFn := func(obj interface{}) {
		enqueueFn(obj, "add")
	}
	informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc:    addEnqueueFn,
		UpdateFunc: nil,
		DeleteFunc: deletionEnqueueFn,
	})
}

func buildSqsMsg(pwe PodWatchEvent) (report.SqsMessage, error) {
	b, err := json.Marshal(pwe)
	if err != nil {
		return report.SqsMessage{}, err
	}
	return report.SqsMessage{
		Message: string(b),
		Attributes: map[string]string{
			scrape.TypeAttributeName:   scrape.EventMessage,
			scrape.ObjectAttributeName: scrape.PodObject,
			scrape.FromAttributeName:   conf.HostName,
		},
	}, nil
}
