package service_test

import (
	"context"
	"errors"
	"testing"

	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"

	coremodel "security-center-backend/internal/model"
	"security-center-backend/internal/modules/caasm/mocks"
	caasmmodel "security-center-backend/internal/modules/caasm/model"
	"security-center-backend/internal/modules/caasm/service"
)

func TestPhase5RelationshipGraphReturnsNodesAndEdges(t *testing.T) {
	repo := &mocks.MockAssetRepository{}
	repo.On("ListRelationships", mock.Anything, mock.Anything).
		Return([]caasmmodel.AssetRelationship{
			{SourceAssetID: 1, TargetAssetID: 2, RelationshipType: "connects_to"},
			{SourceAssetID: 2, TargetAssetID: 3, RelationshipType: "depends_on"},
		}, nil)
	repo.On("ListByIDs", mock.Anything, mock.Anything).
		Return([]caasmmodel.Asset{
			{Base: coremodel.Base{ID: 1}, NativeID: "i-001", Name: "gateway", AssetType: caasmmodel.AssetTypeCompute},
			{Base: coremodel.Base{ID: 2}, NativeID: "i-002", Name: "db", AssetType: caasmmodel.AssetTypeStorage},
			// id=3 故意缺失：验证占位节点兜底
		}, nil)
	svc := service.NewAssetService(repo, nil)

	graph, err := svc.GetRelationshipGraph(context.Background())

	require.NoError(t, err)
	require.NotNil(t, graph)
	require.Len(t, graph.Edges, 2)
	require.Equal(t, "connects_to", graph.Edges[0].Label)
	require.Len(t, graph.Nodes, 3)
	// 节点按 id 升序：1、2 有资产信息，3 为占位节点
	require.Equal(t, "1", graph.Nodes[0].ID)
	require.Equal(t, "gateway", graph.Nodes[0].Label)
	require.Equal(t, "compute", graph.Nodes[0].Type)
	require.Equal(t, "2", graph.Nodes[1].ID)
	require.Equal(t, "3", graph.Nodes[2].ID)
	require.Equal(t, "unknown", graph.Nodes[2].Type)
	edge := graph.Edges[0]
	require.Equal(t, "1", edge.Source)
	require.Equal(t, "2", edge.Target)
	repo.AssertExpectations(t)
}

func TestPhase5RelationshipGraphEmptyRelationshipsReturnsEmptyGraph(t *testing.T) {
	repo := &mocks.MockAssetRepository{}
	repo.On("ListRelationships", mock.Anything, mock.Anything).
		Return([]caasmmodel.AssetRelationship{}, nil)
	svc := service.NewAssetService(repo, nil)

	graph, err := svc.GetRelationshipGraph(context.Background())

	require.NoError(t, err)
	require.NotNil(t, graph)
	require.Empty(t, graph.Nodes)
	require.Empty(t, graph.Edges)
	repo.AssertExpectations(t)
}

func TestPhase5RelationshipGraphRepositoryErrorPropagates(t *testing.T) {
	repo := &mocks.MockAssetRepository{}
	repo.On("ListRelationships", mock.Anything, mock.Anything).
		Return(nil, errors.New("db down"))
	svc := service.NewAssetService(repo, nil)

	graph, err := svc.GetRelationshipGraph(context.Background())

	require.Nil(t, graph)
	require.Error(t, err)
	require.Contains(t, err.Error(), "db down")
	repo.AssertExpectations(t)
}
