package app

import (
	"fmt"
	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
	"verification-platform-backend/pkg/crypto"

	"github.com/gin-gonic/gin"
)

func AppCryptoMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		fmt.Printf("[AppCrypto] Middleware called\n")
		appKey := c.Param("appKey")
		fmt.Printf("[AppCrypto] AppKey from param: %s\n", appKey)

		if appKey == "" {
			fmt.Printf("[AppCrypto] AppKey is empty, skipping\n")
			c.Next()
			return
		}

		var app model.Application
		if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
			fmt.Printf("[AppCrypto] Database error: %v\n", err)
			c.Next()
			return
		}

		fmt.Printf("[AppCrypto] App found: %+v\n", app)

		var encryptType crypto.EncryptType
		switch app.EncryptType {
		case "aes":
			encryptType = crypto.EncryptTypeAES
		case "rc4":
			encryptType = crypto.EncryptTypeRC4
		default:
			encryptType = crypto.EncryptTypeNone
		}

		shouldEncrypt := encryptType != crypto.EncryptTypeNone

		fmt.Printf("[AppCrypto] AppKey: %s, EncryptType: %s, EncryptKey: %s, ShouldEncrypt: %v\n",
			appKey, app.EncryptType, app.EncryptKey, shouldEncrypt)

		c.Set("should_encrypt_response", shouldEncrypt)
		c.Set("crypto_manager", crypto.NewCryptoManager(encryptType, app.EncryptKey))

		c.Next()
	}
}

func getAppCryptoManager(appKey string) (*crypto.CryptoManager, error) {
	var app model.Application
	if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
		return nil, err
	}

	var encryptType crypto.EncryptType
	switch app.EncryptType {
	case "aes":
		encryptType = crypto.EncryptTypeAES
	case "rc4":
		encryptType = crypto.EncryptTypeRC4
	default:
		encryptType = crypto.EncryptTypeNone
	}

	return crypto.NewCryptoManager(encryptType, app.EncryptKey), nil
}

func decryptRequest(c *gin.Context, appKey string) ([]byte, error) {
	encryptedData := c.GetHeader("X-Encrypted-Data")
	if encryptedData == "" {
		return nil, nil
	}

	cryptoManager, err := getAppCryptoManager(appKey)
	if err != nil {
		return nil, err
	}

	decrypted, err := cryptoManager.Decrypt(encryptedData)
	if err != nil {
		return nil, err
	}

	return []byte(decrypted), nil
}

func encryptResponse(c *gin.Context, appKey string, data []byte) (string, error) {
	cryptoManager, err := getAppCryptoManager(appKey)
	if err != nil {
		return "", err
	}

	return cryptoManager.Encrypt(string(data))
}
