package plugins

import (
	"context"
	"encoding/json"
	"os"
	"path/filepath"
	"testing"
)

func TestDirectoryRegistryScansInstalledPlugins(t *testing.T) {
	root := t.TempDir()
	pluginDir := filepath.Join(root, "aliyun-sms", "1.0.0")
	if err := os.MkdirAll(pluginDir, 0o755); err != nil {
		t.Fatal(err)
	}
	manifest := Manifest{
		SchemaVersion: 1,
		ID:            "aliyun-sms",
		Name:          "Aliyun SMS",
		Version:       "1.0.0",
		Runtime:       RuntimeJSONRPC,
		Entry:         map[string]string{"default": "bin/plugin"},
		Capabilities:  []string{CapabilitySMS},
		Requirements: map[string]any{
			"python_packages": []string{},
			"network":         []string{"Aliyun SMS API"},
		},
		Provider:      "plugin:aliyun-sms",
		ManageActions: []map[string]any{{"key": "sync"}},
		ProductPage:   map[string]any{"purchase_fields": []any{}},
	}
	raw, _ := json.Marshal(manifest)
	if err := os.WriteFile(filepath.Join(pluginDir, "plugin.json"), raw, 0o644); err != nil {
		t.Fatal(err)
	}

	registry := NewDirectoryRegistry([]string{root})
	got, err := registry.Resolve(context.Background(), "aliyun-sms", CapabilitySMS)
	if err != nil {
		t.Fatalf("Resolve() error = %v", err)
	}
	if got.ID != "aliyun-sms" || got.Dir != pluginDir {
		t.Fatalf("unexpected manifest: %#v", got)
	}
	network, ok := got.Requirements["network"].([]any)
	if !ok || len(network) != 1 || network[0] != "Aliyun SMS API" {
		t.Fatalf("requirements were not preserved: %#v", got.Requirements)
	}
	if _, err := registry.Resolve(context.Background(), "aliyun-sms", CapabilityEmail); err == nil {
		t.Fatal("Resolve() should reject missing capability")
	}
	if got.Provider != "plugin:aliyun-sms" || len(got.ManageActions) != 1 || got.ProductPage == nil {
		t.Fatalf("workflow metadata was not preserved: %#v", got)
	}
}

type fakeCaller struct {
	method string
	params any
}

func (f *fakeCaller) Call(ctx context.Context, manifest Manifest, method string, params any, result any) error {
	_ = ctx
	_ = manifest
	f.method = method
	f.params = params
	raw, _ := json.Marshal(map[string]any{"ok": true, "message_id": "sms-1"})
	return json.Unmarshal(raw, result)
}

func TestServiceSendSMSUsesCommonCallLayer(t *testing.T) {
	registry := NewDirectoryRegistry(nil)
	registry.items = map[string]Manifest{
		"sms-demo": {
			ID:           "sms-demo",
			Name:         "SMS Demo",
			Version:      "1.0.0",
			Runtime:      RuntimeJSONRPC,
			Capabilities: []string{CapabilitySMS},
			Entry:        map[string]string{"default": "demo"},
			Enabled:      true,
			Status:       "enabled",
		},
	}
	caller := &fakeCaller{}
	service := NewServiceWith(registry, caller, nil)

	resp, err := service.SendSMS(context.Background(), "sms-demo", SMSSendRequest{Phone: "13800000000", Code: "123456"})
	if err != nil {
		t.Fatalf("SendSMS() error = %v", err)
	}
	if !resp.OK || resp.MessageID != "sms-1" {
		t.Fatalf("unexpected response: %#v", resp)
	}
	if caller.method != MethodSMSSend {
		t.Fatalf("method = %s, want %s", caller.method, MethodSMSSend)
	}
}
