package app

import (
	"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) {
		appKey := c.Param("appKey")

		if appKey == "" {
			c.Next()
			return
		}

		if database.DB == nil {
			c.JSON(500, gin.H{"code": 500, "message": "数据库未初始化"})
			c.Abort()
			return
		}

		var app model.Application
		if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
			c.JSON(404, gin.H{"code": 404, "message": "应用不存在"})
			c.Abort()
			return
		}

		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

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

		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))
}
