package automation

import (
	"testing"

	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/stretchr/testify/assert"
)

func TestSubmitRequest_Validation(t *testing.T) {
	// Arrange
	req := SubmitRequest{
		ObjectAPIName: "Opportunity",
		RecordID:      "opp-123",
		Comments:      "Requesting approval for this deal",
	}

	// Assert
	assert.Equal(t, "Opportunity", req.ObjectAPIName)
	assert.Equal(t, "opp-123", req.RecordID)
	assert.NotEmpty(t, req.Comments)
}

func TestApprovalService_IsAuthorizedApprover(t *testing.T) {
	tests := []struct {
		name     string
		item     models.SObject
		user     *models.UserSession
		expected bool
	}{
		{
			name: "User is assigned approver",
			item: models.SObject{
				constants.FieldApproverID: "user-123",
			},
			user:     &models.UserSession{ID: "user-123"},
			expected: true,
		},
		{
			name: "User is not assigned approver",
			item: models.SObject{
				constants.FieldApproverID: "user-456",
			},
			user:     &models.UserSession{ID: "user-123"},
			expected: false,
		},
		{
			name:     "Missing approver field",
			item:     models.SObject{},
			user:     &models.UserSession{ID: "user-123"},
			expected: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Simple check matching the isAuthorizedApprover logic
			approverID, _ := tt.item[constants.FieldApproverID].(string)
			result := approverID == tt.user.ID
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestApprovalService_StatusTransitions(t *testing.T) {
	// Test valid status transitions using shared constants
	statusTransitions := map[string][]string{
		constants.ApprovalStatusPending:  {constants.ApprovalStatusApproved, constants.ApprovalStatusRejected},
		constants.ApprovalStatusApproved: {},
		constants.ApprovalStatusRejected: {},
	}

	// Validate Pending can transition to Approved or Rejected
	assert.Contains(t, statusTransitions[constants.ApprovalStatusPending], constants.ApprovalStatusApproved)
	assert.Contains(t, statusTransitions[constants.ApprovalStatusPending], constants.ApprovalStatusRejected)

	// Validate terminal states have no transitions
	assert.Empty(t, statusTransitions[constants.ApprovalStatusApproved])
	assert.Empty(t, statusTransitions[constants.ApprovalStatusRejected])
}

func TestApprovalService_WorkItemFields(t *testing.T) {
	// Test work item structure
	workItem := models.SObject{
		constants.FieldID:            "wi-123",
		constants.FieldRecordID:      "opp-456",
		constants.FieldObjectAPIName: "Opportunity",
		constants.FieldApproverID:    "user-789",
		constants.FieldStatus:        constants.ApprovalStatusPending,
		constants.FieldComments:      "Please review",
	}

	assert.Equal(t, "wi-123", workItem[constants.FieldID])
	assert.Equal(t, "opp-456", workItem[constants.FieldRecordID])
	assert.Equal(t, "Opportunity", workItem[constants.FieldObjectAPIName])
	assert.Equal(t, constants.ApprovalStatusPending, workItem[constants.FieldStatus])
}

func TestCloneApprovalMetadataRecord_StripsManagedFields(t *testing.T) {
	source := models.SObject{
		constants.FieldID:               "proc-1",
		constants.FieldCreatedDate:      "2026-01-01T00:00:00Z",
		constants.FieldCreatedByID:      "u-1",
		constants.FieldLastModifiedDate: "2026-01-02T00:00:00Z",
		constants.FieldLastModifiedByID: "u-2",
		"Name":                          "Original",
		"DeveloperName":                 "Original_Process",
	}

	cloned := cloneApprovalMetadataRecord(source)

	assert.NotContains(t, cloned, constants.FieldID)
	assert.NotContains(t, cloned, constants.FieldCreatedDate)
	assert.NotContains(t, cloned, constants.FieldCreatedByID)
	assert.NotContains(t, cloned, constants.FieldLastModifiedDate)
	assert.NotContains(t, cloned, constants.FieldLastModifiedByID)
	assert.Equal(t, "Original", cloned["Name"])
	assert.Equal(t, "Original_Process", cloned["DeveloperName"])
}
