/*
 * Copyright (c) 2026 Huawei Technologies Co., Ltd.
 * openFuyao is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package controller

import (
	"context"
	"errors"
	"testing"
	"time"

	"many-core-orchestrator/api/v1alpha1"

	olog "gopkg.openfuyao.cn/common-modules/ologger/log"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

type recordingRuleStore struct {
	applied int
	deleted int
	err     error
}

func (s *recordingRuleStore) ApplyDetectionRuleConfig(event string, ruleConfig *v1alpha1.DetectionRuleConfig) error {
	s.applied++
	return s.err
}

func (s *recordingRuleStore) KeepLastValidAfterDelete() {
	s.deleted++
}

func TestDetectionRuleConfigReconciler(t *testing.T) {
	scheme := runtime.NewScheme()
	if err := v1alpha1.AddToScheme(scheme); err != nil {
		t.Fatal(err)
	}
	obj := &v1alpha1.DetectionRuleConfig{ObjectMeta: metav1.ObjectMeta{Name: "cluster", Namespace: "mco-system"}}
	client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(obj).Build()
	store := &recordingRuleStore{}
	reconciler := &DetectionRuleConfigReconciler{
		Client:    client,
		store:     store,
		logger:    olog.With("test", "controller"),
		namespace: "mco-system",
		name:      "cluster",
	}

	if result, err := reconciler.Reconcile(context.Background(), ctrl.Request{NamespacedName: types.NamespacedName{Namespace: "other", Name: "cluster"}}); err != nil || result != (ctrl.Result{}) {
		t.Fatalf("ignored result=%+v err=%v", result, err)
	}
	if result, err := reconciler.Reconcile(context.Background(), ctrl.Request{NamespacedName: types.NamespacedName{Namespace: "mco-system", Name: "cluster"}}); err != nil || result != (ctrl.Result{}) {
		t.Fatalf("result=%+v err=%v", result, err)
	}
	if store.applied != 1 {
		t.Fatalf("applied=%d", store.applied)
	}

	store.err = errors.New("bad config")
	result, err := reconciler.Reconcile(context.Background(), ctrl.Request{NamespacedName: types.NamespacedName{Namespace: "mco-system", Name: "cluster"}})
	if err != nil || result.RequeueAfter != 10*time.Second {
		t.Fatalf("bad config result=%+v err=%v", result, err)
	}

	if err := client.Delete(context.Background(), obj); err != nil {
		t.Fatal(err)
	}
	store.err = nil
	result, err = reconciler.Reconcile(context.Background(), ctrl.Request{NamespacedName: types.NamespacedName{Namespace: "mco-system", Name: "cluster"}})
	if err != nil || result != (ctrl.Result{}) || store.deleted != 1 {
		t.Fatalf("delete result=%+v err=%v deleted=%d", result, err, store.deleted)
	}
}