package converter

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
)

// TestToAgentReviewFilePreservesToken verifies the per-file opaque token
// survives the agent → dto conversion. The token is the frontend's
// change-detection signal for a single file row; dropping it here would force
// the frontend to re-fetch every file diff on every snapshot poll, defeating
// the fingerprint optimization.
func TestToAgentReviewFilePreservesToken(t *testing.T) {
	src := agent.AgentReviewFile{
		Path:               "main.go",
		OldPath:            "main.old.go",
		ChangeType:         "R",
		Staged:             true,
		Unstaged:           false,
		StagedChangeType:   "M",
		UnstagedChangeType: "",
		Token:              "abcdef0123456789",
	}
	got := ToAgentReviewFile(src)
	require.Equal(t, dto.AgentReviewFile{
		Path:               "main.go",
		OldPath:            "main.old.go",
		ChangeType:         "R",
		Staged:             true,
		Unstaged:           false,
		StagedChangeType:   "M",
		UnstagedChangeType: "",
		Token:              "abcdef0123456789",
	}, got, "ToAgentReviewFile must mirror every field including Token")
}

// TestAgentReviewFileJSONRoundTrip verifies the per-file opaque token
// survives dto → JSON → dto round-trip. The token travels from desktop
// (types.ReviewFile.Token) over the daemon wire (as part of
// reviewFilesResultMessage.Files) through the hub (agent.AgentReviewFile) to
// the HTTP response (dto.AgentReviewFile). This test pins the dto ↔ JSON
// leg so a future struct-tag drift cannot silently drop the field.
func TestAgentReviewFileJSONRoundTrip(t *testing.T) {
	src := dto.AgentReviewFile{
		Path:       "main.go",
		ChangeType: "M",
		Token:      "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
	}
	raw, err := json.Marshal(src)
	require.NoError(t, err, "marshal")
	require.Contains(t, string(raw), `"token":"abcdef`, "JSON must include the token field")

	var dst dto.AgentReviewFile
	require.NoError(t, json.Unmarshal(raw, &dst), "unmarshal")
	require.Equal(t, src, dst, "round-trip must preserve Token")
}

// TestAgentReviewFileJSONOmitsEmptyToken verifies the token field is omitted
// when empty, so legacy file rows (and the unsupported-git fallback path)
// do not pollute the wire with `"token":""`.
func TestAgentReviewFileJSONOmitsEmptyToken(t *testing.T) {
	raw, err := json.Marshal(dto.AgentReviewFile{Path: "main.go", ChangeType: "M"})
	require.NoError(t, err)
	require.NotContains(t, string(raw), `"token"`, "empty token must be omitted from JSON")
}

func TestToReviewIncludesProjectID(t *testing.T) {
	review := ToReview(&agent.ReviewContext{
		ID:          "rcx_1",
		WorkspaceID: "wsp_1",
		ProjectID:   "prj_1",
		MachineID:   "mac_1",
		RootPath:    "/repo/one",
		DisplayName: "One",
	})
	require.NotNil(t, review)
	require.Equal(t, "prj_1", review.ProjectID)
}
