package constants

import (
	"context"
	"testing"
)

func TestStandardActionInternalAccessScope_MatchesOnlyStampedActionObjectOperation(t *testing.T) {
	ctx := WithStandardActionInternalAccessScopes(context.Background(), "sa_convertlead", []StandardActionInternalAccessScope{
		{StandardActionID: "sa_convertlead", ObjectAPIName: "Task", Operation: PermEdit},
		{StandardActionID: "sa_convertlead", ObjectAPIName: "Task", Operation: PermRead},
	})

	if !IsScopedInternalAccess(ctx, "Task", PermEdit) {
		t.Fatal("expected matching standard-action internal access scope")
	}
	if !IsScopedInternalAccess(ctx, "Task", PermRead) {
		t.Fatal("expected read operation to be supported by standard-action internal access scope")
	}
	if IsScopedInternalAccess(ctx, "Task", PermCreate) {
		t.Fatal("operation mismatch must not inherit scoped access permission")
	}
	if IsScopedInternalAccess(ctx, "CampaignMember", PermEdit) {
		t.Fatal("object mismatch must not inherit scoped access permission")
	}

	otherActionCtx := WithStandardActionInternalAccessScopes(context.Background(), "sa_other", []StandardActionInternalAccessScope{
		{StandardActionID: "sa_convertlead", ObjectAPIName: "Task", Operation: PermEdit},
	})
	if IsScopedInternalAccess(otherActionCtx, "Task", PermEdit) {
		t.Fatal("scope rows for another standard action must not apply")
	}
}

func TestWithoutStandardActionInternalAccessScopes_StripsStampedScopes(t *testing.T) {
	ctx := WithStandardActionInternalAccessScopes(context.Background(), "sa_convertlead", []StandardActionInternalAccessScope{
		{StandardActionID: "sa_convertlead", ObjectAPIName: "Task", Operation: PermEdit},
	})
	if !HasStandardActionInternalAccessScopes(ctx) {
		t.Fatal("expected stamped standard-action internal scopes")
	}

	stripped := WithoutStandardActionInternalAccessScopes(ctx)
	if HasStandardActionInternalAccessScopes(stripped) {
		t.Fatal("expected standard-action internal scopes to be stripped")
	}
	if IsScopedInternalAccess(stripped, "Task", PermEdit) {
		t.Fatal("stripped context must not grant scoped internal access")
	}
	if !HasStandardActionExecutionContext(stripped) {
		t.Fatal("stripping internal scopes must preserve the authorized standard-action execution context")
	}
}

func TestStandardActionExecutionContext_DoesNotGrantInternalAccess(t *testing.T) {
	ctx := WithStandardActionExecutionContext(context.Background(), "sa_convertlead")
	if !HasStandardActionExecutionContext(ctx) {
		t.Fatal("expected standard-action execution context")
	}
	if HasStandardActionInternalAccessScopes(ctx) {
		t.Fatal("execution context alone must not grant internal access scopes")
	}
	if IsScopedInternalAccess(ctx, "Task", PermEdit) {
		t.Fatal("execution context alone must not grant scoped internal access")
	}
}

func TestStandardActionExecutionRootFlow_MatchesOnlyOwnedRoot(t *testing.T) {
	ctx := WithStandardActionExecutionRootFlow(context.Background(), "sa_convertlead", "Std_ConvertLead")
	if !StandardActionExecutionOwnsRootFlow(ctx, "std_convertlead") {
		t.Fatal("expected standard action context to own its root flow case-insensitively")
	}
	if StandardActionExecutionOwnsRootFlow(ctx, "Std_RelinkLeadChildren") {
		t.Fatal("standard action root must not match a different protected flow")
	}
	if HasStandardActionProtectedFlowExecution(ctx) {
		t.Fatal("root ownership alone must not mark nested protected-flow execution as authorized")
	}

	ctx = WithStandardActionProtectedFlowExecution(ctx, "Std_ConvertLead")
	if !HasStandardActionProtectedFlowExecution(ctx) {
		t.Fatal("expected protected-flow execution marker")
	}

	stripped := WithoutStandardActionProtectedFlowExecution(ctx)
	if HasStandardActionProtectedFlowExecution(stripped) {
		t.Fatal("expected protected-flow execution marker to be stripped")
	}
	if !StandardActionExecutionOwnsRootFlow(stripped, "Std_ConvertLead") {
		t.Fatal("stripping protected-flow marker must preserve the standard-action root ownership context")
	}
}
