package handlers

import (
	"context"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"testing"

	"github.com/Wikid82/charon/backend/internal/models"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

func TestCrowdsecWave7_ReadAcquisitionConfig_ReadErrorOnDirectory(t *testing.T) {
	tmpDir := t.TempDir()
	acqDir := filepath.Join(tmpDir, "acq")
	require.NoError(t, os.MkdirAll(acqDir, 0o750))

	_, err := readAcquisitionConfig(acqDir)
	require.Error(t, err)
	require.Contains(t, err.Error(), "read acquisition config")
}

func TestCrowdsecWave7_Start_CreateSecurityConfigFailsOnReadOnlyDB(t *testing.T) {

	tmpDir := t.TempDir()
	dbPath := filepath.Join(tmpDir, "crowdsec-readonly.db")

	rwDB, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
	require.NoError(t, err)
	require.NoError(t, rwDB.AutoMigrate(&models.SecurityConfig{}, &models.Setting{}))

	sqlDB, err := rwDB.DB()
	require.NoError(t, err)
	require.NoError(t, sqlDB.Close())

	roDB, err := gorm.Open(sqlite.Open("file:"+dbPath+"?mode=ro"), &gorm.Config{})
	require.NoError(t, err)

	h := newTestCrowdsecHandler(t, roDB, &fakeExec{}, "/bin/false", t.TempDir())

	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest(http.MethodPost, "/api/v1/admin/crowdsec/start", nil)

	h.Start(c)

	require.Equal(t, http.StatusInternalServerError, w.Code)
	require.Contains(t, w.Body.String(), "Failed to persist configuration")
}

func TestCrowdsecWave7_EnsureBouncerRegistration_InvalidFileKeyReRegisters(t *testing.T) {
	tmpDir := t.TempDir()
	keyPath := tmpDir + "/bouncer_key"
	require.NoError(t, saveKeyToFile(keyPath, "invalid-file-key"))

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusForbidden)
	}))
	defer server.Close()

	db := setupCrowdDB(t)
	handler := newTestCrowdsecHandler(t, db, &fakeExec{}, "/bin/false", tmpDir)
	t.Setenv("CHARON_CROWDSEC_BOUNCER_KEY_PATH", keyPath)

	cfg := models.SecurityConfig{
		UUID:           uuid.New().String(),
		Name:           "default",
		CrowdSecAPIURL: server.URL,
	}
	require.NoError(t, db.Create(&cfg).Error)

	mockCmdExec := new(MockCommandExecutor)
	mockCmdExec.On("Execute", mock.Anything, "cscli", mock.MatchedBy(func(args []string) bool {
		return len(args) >= 2 && args[0] == "bouncers" && args[1] == "delete"
	})).Return([]byte("deleted"), nil)
	mockCmdExec.On("Execute", mock.Anything, "cscli", mock.MatchedBy(func(args []string) bool {
		return len(args) >= 2 && args[0] == "bouncers" && args[1] == "add"
	})).Return([]byte("new-file-key-1234567890"), nil)
	handler.CmdExec = mockCmdExec

	key, err := handler.ensureBouncerRegistration(context.Background())
	require.NoError(t, err)
	require.Equal(t, "new-file-key-1234567890", key)
	require.Equal(t, "new-file-key-1234567890", readKeyFromFile(keyPath))
	mockCmdExec.AssertExpectations(t)
}
