package app

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"strings"
	"sync"

	"GoNavi-Wails/internal/connection"
	"GoNavi-Wails/internal/logger"
	"GoNavi-Wails/internal/redis"
)

// Redis client cache
var (
	redisCache   = make(map[string]redis.RedisClient)
	redisCacheMu sync.Mutex
)

// getRedisClient gets or creates a Redis client from cache
func (a *App) getRedisClient(config connection.ConnectionConfig) (redis.RedisClient, error) {
	key := getRedisClientCacheKey(config)
	shortKey := key
	if len(shortKey) > 12 {
		shortKey = shortKey[:12]
	}
	logger.Infof("获取 Redis 连接：%s 缓存Key=%s", formatRedisConnSummary(config), shortKey)

	redisCacheMu.Lock()
	defer redisCacheMu.Unlock()

	if client, ok := redisCache[key]; ok {
		logger.Infof("命中 Redis 连接缓存，开始检测可用性：缓存Key=%s", shortKey)
		if err := client.Ping(); err == nil {
			logger.Infof("缓存 Redis 连接可用：缓存Key=%s", shortKey)
			return client, nil
		} else {
			logger.Error(err, "缓存 Redis 连接不可用，准备重建：缓存Key=%s", shortKey)
		}
		client.Close()
		delete(redisCache, key)
	}

	logger.Infof("创建 Redis 客户端实例：缓存Key=%s", shortKey)
	client := redis.NewRedisClient()
	if err := client.Connect(config); err != nil {
		logger.Error(err, "Redis 连接失败：%s 缓存Key=%s", formatRedisConnSummary(config), shortKey)
		return nil, err
	}

	redisCache[key] = client
	logger.Infof("Redis 连接成功并写入缓存：%s 缓存Key=%s", formatRedisConnSummary(config), shortKey)
	return client, nil
}

func getRedisClientCacheKey(config connection.ConnectionConfig) string {
	if !config.UseSSH {
		config.SSH = connection.SSHConfig{}
	}
	b, _ := json.Marshal(config)
	sum := sha256.Sum256(b)
	return hex.EncodeToString(sum[:])
}

func formatRedisConnSummary(config connection.ConnectionConfig) string {
	timeoutSeconds := config.Timeout
	if timeoutSeconds <= 0 {
		timeoutSeconds = 30
	}

	var b strings.Builder
	b.WriteString("类型=redis 地址=")
	b.WriteString(config.Host)
	b.WriteString(":")
	b.WriteString(string(rune(config.Port + '0')))
	b.WriteString(" DB=")
	b.WriteString(string(rune(config.RedisDB + '0')))

	if config.UseSSH {
		b.WriteString(" SSH=")
		b.WriteString(config.SSH.Host)
		b.WriteString(":")
		b.WriteString(string(rune(config.SSH.Port + '0')))
		b.WriteString(" 用户=")
		b.WriteString(config.SSH.User)
	}

	return b.String()
}

// RedisConnect tests a Redis connection
func (a *App) RedisConnect(config connection.ConnectionConfig) connection.QueryResult {
	config.Type = "redis"
	_, err := a.getRedisClient(config)
	if err != nil {
		logger.Error(err, "RedisConnect 连接失败：%s", formatRedisConnSummary(config))
		return connection.QueryResult{Success: false, Message: err.Error()}
	}
	logger.Infof("RedisConnect 连接成功：%s", formatRedisConnSummary(config))
	return connection.QueryResult{Success: true, Message: "连接成功"}
}

// RedisTestConnection tests a Redis connection (alias for RedisConnect)
func (a *App) RedisTestConnection(config connection.ConnectionConfig) connection.QueryResult {
	return a.RedisConnect(config)
}

// RedisScanKeys scans keys matching a pattern
func (a *App) RedisScanKeys(config connection.ConnectionConfig, pattern string, cursor uint64, count int64) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	result, err := client.ScanKeys(pattern, cursor, count)
	if err != nil {
		logger.Error(err, "RedisScanKeys 扫描失败：pattern=%s", pattern)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Data: result}
}

// RedisGetValue gets the value of a key
func (a *App) RedisGetValue(config connection.ConnectionConfig, key string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	value, err := client.GetValue(key)
	if err != nil {
		logger.Error(err, "RedisGetValue 获取失败：key=%s", key)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Data: value}
}

// RedisSetString sets a string value
func (a *App) RedisSetString(config connection.ConnectionConfig, key, value string, ttl int64) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.SetString(key, value, ttl); err != nil {
		logger.Error(err, "RedisSetString 设置失败：key=%s", key)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "设置成功"}
}

// RedisSetHashField sets a field in a hash
func (a *App) RedisSetHashField(config connection.ConnectionConfig, key, field, value string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.SetHashField(key, field, value); err != nil {
		logger.Error(err, "RedisSetHashField 设置失败：key=%s field=%s", key, field)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "设置成功"}
}

// RedisDeleteKeys deletes one or more keys
func (a *App) RedisDeleteKeys(config connection.ConnectionConfig, keys []string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	deleted, err := client.DeleteKeys(keys)
	if err != nil {
		logger.Error(err, "RedisDeleteKeys 删除失败：keys=%v", keys)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Data: map[string]int64{"deleted": deleted}}
}

// RedisSetTTL sets the TTL of a key
func (a *App) RedisSetTTL(config connection.ConnectionConfig, key string, ttl int64) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.SetTTL(key, ttl); err != nil {
		logger.Error(err, "RedisSetTTL 设置失败：key=%s ttl=%d", key, ttl)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "设置成功"}
}

// RedisExecuteCommand executes a raw Redis command
func (a *App) RedisExecuteCommand(config connection.ConnectionConfig, command string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	// Parse command string into args
	args := parseRedisCommand(command)
	if len(args) == 0 {
		return connection.QueryResult{Success: false, Message: "命令不能为空"}
	}

	result, err := client.ExecuteCommand(args)
	if err != nil {
		logger.Error(err, "RedisExecuteCommand 执行失败：command=%s", command)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Data: result}
}

// parseRedisCommand parses a Redis command string into arguments
func parseRedisCommand(command string) []string {
	command = strings.TrimSpace(command)
	if command == "" {
		return nil
	}

	var args []string
	var current strings.Builder
	inQuote := false
	quoteChar := rune(0)

	for _, ch := range command {
		if inQuote {
			if ch == quoteChar {
				inQuote = false
				args = append(args, current.String())
				current.Reset()
			} else {
				current.WriteRune(ch)
			}
		} else {
			if ch == '"' || ch == '\'' {
				inQuote = true
				quoteChar = ch
			} else if ch == ' ' || ch == '\t' {
				if current.Len() > 0 {
					args = append(args, current.String())
					current.Reset()
				}
			} else {
				current.WriteRune(ch)
			}
		}
	}

	if current.Len() > 0 {
		args = append(args, current.String())
	}

	return args
}

// RedisGetServerInfo returns server information
func (a *App) RedisGetServerInfo(config connection.ConnectionConfig) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	info, err := client.GetServerInfo()
	if err != nil {
		logger.Error(err, "RedisGetServerInfo 获取失败")
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Data: info}
}

// RedisGetDatabases returns information about all databases
func (a *App) RedisGetDatabases(config connection.ConnectionConfig) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	dbs, err := client.GetDatabases()
	if err != nil {
		logger.Error(err, "RedisGetDatabases 获取失败")
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Data: dbs}
}

// RedisSelectDB selects a database
func (a *App) RedisSelectDB(config connection.ConnectionConfig, dbIndex int) connection.QueryResult {
	config.Type = "redis"
	config.RedisDB = dbIndex
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.SelectDB(dbIndex); err != nil {
		logger.Error(err, "RedisSelectDB 切换失败：db=%d", dbIndex)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "切换成功"}
}

// RedisRenameKey renames a key
func (a *App) RedisRenameKey(config connection.ConnectionConfig, oldKey, newKey string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.RenameKey(oldKey, newKey); err != nil {
		logger.Error(err, "RedisRenameKey 重命名失败：%s -> %s", oldKey, newKey)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "重命名成功"}
}

// RedisDeleteHashField deletes fields from a hash
func (a *App) RedisDeleteHashField(config connection.ConnectionConfig, key string, fields []string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.DeleteHashField(key, fields...); err != nil {
		logger.Error(err, "RedisDeleteHashField 删除失败：key=%s fields=%v", key, fields)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "删除成功"}
}

// RedisListPush pushes values to a list
func (a *App) RedisListPush(config connection.ConnectionConfig, key string, values []string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.ListPush(key, values...); err != nil {
		logger.Error(err, "RedisListPush 添加失败：key=%s", key)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "添加成功"}
}

// RedisListSet sets a value at an index in a list
func (a *App) RedisListSet(config connection.ConnectionConfig, key string, index int64, value string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.ListSet(key, index, value); err != nil {
		logger.Error(err, "RedisListSet 设置失败：key=%s index=%d", key, index)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "设置成功"}
}

// RedisSetAdd adds members to a set
func (a *App) RedisSetAdd(config connection.ConnectionConfig, key string, members []string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.SetAdd(key, members...); err != nil {
		logger.Error(err, "RedisSetAdd 添加失败：key=%s", key)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "添加成功"}
}

// RedisSetRemove removes members from a set
func (a *App) RedisSetRemove(config connection.ConnectionConfig, key string, members []string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.SetRemove(key, members...); err != nil {
		logger.Error(err, "RedisSetRemove 删除失败：key=%s", key)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "删除成功"}
}

// RedisZSetAdd adds members to a sorted set
func (a *App) RedisZSetAdd(config connection.ConnectionConfig, key string, members []redis.ZSetMember) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.ZSetAdd(key, members...); err != nil {
		logger.Error(err, "RedisZSetAdd 添加失败：key=%s", key)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "添加成功"}
}

// RedisZSetRemove removes members from a sorted set
func (a *App) RedisZSetRemove(config connection.ConnectionConfig, key string, members []string) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.ZSetRemove(key, members...); err != nil {
		logger.Error(err, "RedisZSetRemove 删除失败：key=%s", key)
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "删除成功"}
}

// RedisFlushDB flushes the current database
func (a *App) RedisFlushDB(config connection.ConnectionConfig) connection.QueryResult {
	config.Type = "redis"
	client, err := a.getRedisClient(config)
	if err != nil {
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	if err := client.FlushDB(); err != nil {
		logger.Error(err, "RedisFlushDB 清空失败")
		return connection.QueryResult{Success: false, Message: err.Error()}
	}

	return connection.QueryResult{Success: true, Message: "清空成功"}
}

// CloseAllRedisClients closes all cached Redis clients (called on shutdown)
func CloseAllRedisClients() {
	redisCacheMu.Lock()
	defer redisCacheMu.Unlock()

	for key, client := range redisCache {
		if client != nil {
			client.Close()
			logger.Infof("已关闭 Redis 连接：%s", key[:12])
		}
	}
	redisCache = make(map[string]redis.RedisClient)
}
