package integration

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	integrationbiz "kra/internal/biz/integration"
	"strings"

	"kra/internal/integration/mq"
	"kra/internal/integration/runtimeconfig"
	websocketintegration "kra/internal/integration/websocket"
)

// ConnectivityTester probes candidate communication settings without changing
// the active clients or writing anything to sys_integration_configs.
type ConnectivityTester struct {
	store *runtimeconfig.Store
}

func NewConnectivityTester(store *runtimeconfig.Store) *ConnectivityTester {
	return &ConnectivityTester{store: store}
}

func (t *ConnectivityTester) TestIntegration(ctx context.Context, config *integrationbiz.IntegrationConfig) error {
	if config == nil {
		return errors.New("集成配置请求为空")
	}
	values := map[string]any{}
	if err := json.Unmarshal(config.Values, &values); err != nil {
		return fmt.Errorf("解析集成配置失败: %w", err)
	}
	if err := t.restoreMaskedSecrets(config.Kind, config.Provider, values); err != nil {
		return err
	}
	raw, err := json.Marshal(values)
	if err != nil {
		return fmt.Errorf("编码集成配置失败: %w", err)
	}
	switch strings.ToLower(strings.TrimSpace(config.Kind)) {
	case integrationbiz.IntegrationKindMQ:
		return mq.TestConfig(ctx, config.Provider, raw)
	case integrationbiz.IntegrationKindWebSocket:
		if strings.ToLower(strings.TrimSpace(config.Provider)) != websocketintegration.ProviderMelody {
			return fmt.Errorf("不支持的 WebSocket provider %q", config.Provider)
		}
		return websocketintegration.TestConfig(ctx, raw)
	default:
		return fmt.Errorf("不支持测试集成类型 %q", config.Kind)
	}
}

func (t *ConnectivityTester) restoreMaskedSecrets(kind, provider string, values map[string]any) error {
	definition, ok := integrationbiz.IntegrationDefinition(kind, provider)
	if !ok {
		return fmt.Errorf("不支持的集成 %s/%s", kind, provider)
	}
	masked := make(map[string]struct{})
	for _, field := range definition.Fields {
		if field.Secret {
			masked[field.Key] = struct{}{}
		}
	}
	if len(masked) == 0 {
		return nil
	}
	currentValues := map[string]any{}
	if t != nil && t.store != nil {
		if current, exists := t.store.Get(kind, provider); exists {
			_ = json.Unmarshal(current.Values, &currentValues)
		}
	}
	for key := range masked {
		value, _ := values[key].(string)
		if strings.TrimSpace(value) != "******" {
			continue
		}
		prior, _ := currentValues[key].(string)
		if strings.TrimSpace(prior) == "" || strings.TrimSpace(prior) == "******" {
			return fmt.Errorf("配置字段 %s 已脱敏，请重新填写后再测试", key)
		}
		values[key] = prior
	}
	return nil
}
