package operator

import (
	"context"
	"fmt"
	"testing"
	"time"

	"github.com/go-logr/logr"
	"github.com/go-logr/zapr"
	"github.com/stretchr/testify/assert"
	"go.uber.org/zap"
	ctrl "sigs.k8s.io/controller-runtime"

	v1alpha1 "github.com/pfeifferj/container-mom-go/pkg/apis/containermom/v1alpha1"
	"github.com/pfeifferj/container-mom-go/pkg/config"
)

func setupTestLogger() logr.Logger {
	zapLog, err := zap.NewDevelopment()
	if err != nil {
		panic(fmt.Sprintf("failed to create zap logger: %v", err))
	}
	logger := zapr.NewLogger(zapLog)
	ctrl.SetLogger(logger)
	return logger
}

func TestOperator(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping integration test")
	}

	// Set up logging
	setupTestLogger()

	// Create test config
	cfg := &config.Config{
		ListenAddr: ":8081",
		MongoURI:   "mongodb://localhost:27017",
	}

	// Create operator
	op := New(cfg, nil)
	assert.NotNil(t, op)

	// Wait for MongoDB connection
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	err := op.GetMongoDB().Ping(ctx, nil)
	if err != nil {
		t.Skip("MongoDB not available:", err)
	}

	// Test deployment trigger
	err = op.TriggerDeploymentReconcile(context.Background(), "test-deployment")
	assert.Error(t, err) // Should fail because deployment doesn't exist

	// Test MongoDB connection
	client := op.GetMongoDB()
	assert.NotNil(t, client)
	err = client.Ping(context.Background(), nil)
	assert.NoError(t, err)
}

func TestOperatorHealth(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping integration test")
	}

	// Set up logging
	setupTestLogger()

	// Create test config
	cfg := &config.Config{
		ListenAddr: ":8081",
		MongoURI:   "mongodb://localhost:27017",
	}

	// Create operator
	op := New(cfg, nil)
	assert.NotNil(t, op)

	// Wait for MongoDB connection
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	err := op.GetMongoDB().Ping(ctx, nil)
	if err != nil {
		t.Skip("MongoDB not available:", err)
	}

	// Test health check
	err = op.GetMongoDB().Ping(context.Background(), nil)
	assert.NoError(t, err)
}

func TestOperatorBilling(t *testing.T) {
	op := &Operator{}

	t.Run("GetCurrentCustomer", func(t *testing.T) {
		customer, err := op.GetCurrentCustomer(context.Background())
		assert.NoError(t, err)
		assert.Equal(t, "default", customer.Name)
	})

	t.Run("GetResourceUsage", func(t *testing.T) {
		usage, err := op.GetResourceUsage(context.Background(), "test")
		assert.NoError(t, err)
		assert.NotNil(t, usage)
	})

	t.Run("GetBillingHistory", func(t *testing.T) {
		history, err := op.GetBillingHistory(context.Background(), "test")
		assert.NoError(t, err)
		assert.Empty(t, history)
	})

	t.Run("UpdateBillingPlan", func(t *testing.T) {
		err := op.UpdateBillingPlan(context.Background(), "test", "plan")
		assert.NoError(t, err)
	})

	t.Run("UpdateBillingStatus", func(t *testing.T) {
		status := v1alpha1.BillingStatus{
			Status:  "active",
			Message: "test status",
		}
		err := op.UpdateBillingStatus(context.Background(), "test", status)
		assert.NoError(t, err)
	})
}
