package workspaceprotocol_test

import (
	"testing"

	"iop/packages/go/workspaceprotocol"
	iop "iop/proto/gen/iop"
)

func TestWorkspaceTerminalTool(t *testing.T) {
	valid := []struct {
		status  iop.WorkspaceStatus
		code    iop.WorkspaceErrorCode
		message string
	}{
		{iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED, ""},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_READY, "workspace runtime not ready"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSUPPORTED, "workspace operation unsupported"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_FOUND, "workspace entry not found"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST, "workspace request rejected"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_TIMEOUT, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_TIMEOUT, "workspace command timed out"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_CANCELLED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_CANCELLED, "workspace command cancelled"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INTERNAL, "workspace operation failed"},
	}

	for _, tc := range valid {
		msg, ok := workspaceprotocol.ToolTerminal(tc.status, tc.code)
		if !ok || msg != tc.message {
			t.Errorf("ToolTerminal(%v, %v) = (%q, %v), want (%q, true)", tc.status, tc.code, msg, ok, tc.message)
		}
	}

	invalid := []struct {
		status iop.WorkspaceStatus
		code   iop.WorkspaceErrorCode
	}{
		{iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INTERNAL},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_TIMEOUT, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INTERNAL},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_CANCELLED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST},
	}

	for _, tc := range invalid {
		msg, ok := workspaceprotocol.ToolTerminal(tc.status, tc.code)
		if ok {
			t.Errorf("ToolTerminal(%v, %v) unexpectedly succeeded with %q", tc.status, tc.code, msg)
		}
	}
}

func TestWorkspaceTerminalCancel(t *testing.T) {
	valid := []struct {
		status  iop.WorkspaceStatus
		code    iop.WorkspaceErrorCode
		message string
	}{
		{iop.WorkspaceStatus_WORKSPACE_STATUS_CANCELLED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_CANCELLED, "workspace command cancelled"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_FOUND, "workspace command not found"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST, "workspace cancellation rejected"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_READY, "workspace runtime not ready"},
	}

	for _, tc := range valid {
		msg, ok := workspaceprotocol.CancelTerminal(tc.status, tc.code)
		if !ok || msg != tc.message {
			t.Errorf("CancelTerminal(%v, %v) = (%q, %v), want (%q, true)", tc.status, tc.code, msg, ok, tc.message)
		}
	}

	invalid := []struct {
		status iop.WorkspaceStatus
		code   iop.WorkspaceErrorCode
	}{
		{iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_CANCELLED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_CANCELLED},
	}

	for _, tc := range invalid {
		msg, ok := workspaceprotocol.CancelTerminal(tc.status, tc.code)
		if ok {
			t.Errorf("CancelTerminal(%v, %v) unexpectedly succeeded with %q", tc.status, tc.code, msg)
		}
	}
}

func TestWorkspaceTerminalArtifact(t *testing.T) {
	valid := []struct {
		status  iop.WorkspaceStatus
		code    iop.WorkspaceErrorCode
		message string
	}{
		{iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED, ""},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_READY, "workspace runtime not ready"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_FOUND, "workspace artifact not found"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST, "workspace artifact request rejected"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INTERNAL, "workspace artifact operation failed"},
	}
	for _, tc := range valid {
		msg, ok := workspaceprotocol.ArtifactTerminal(tc.status, tc.code)
		if !ok || msg != tc.message {
			t.Errorf("ArtifactTerminal(%v, %v) = (%q, %v), want (%q, true)", tc.status, tc.code, msg, ok, tc.message)
		}
	}

	invalid := []struct {
		status iop.WorkspaceStatus
		code   iop.WorkspaceErrorCode
	}{
		{iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_FOUND},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSUPPORTED},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_TIMEOUT, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_TIMEOUT},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_CANCELLED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_CANCELLED},
	}
	for _, tc := range invalid {
		if msg, ok := workspaceprotocol.ArtifactTerminal(tc.status, tc.code); ok {
			t.Errorf("ArtifactTerminal(%v, %v) unexpectedly succeeded with %q", tc.status, tc.code, msg)
		}
	}
}

func TestWorkspaceTerminalOpenAndCleanup(t *testing.T) {
	if msg, ok := workspaceprotocol.OpenTerminal(iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED); !ok || msg != "" {
		t.Errorf("OpenTerminal success failed: (%q, %v)", msg, ok)
	}
	if msg, ok := workspaceprotocol.OpenTerminal(iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST); !ok || msg != "workspace open rejected" {
		t.Errorf("OpenTerminal error failed: (%q, %v)", msg, ok)
	}
	if _, ok := workspaceprotocol.OpenTerminal(iop.WorkspaceStatus_WORKSPACE_STATUS_CANCELLED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_CANCELLED); ok {
		t.Errorf("OpenTerminal unexpectedly accepted cancelled")
	}

	cleanupValid := []struct {
		status  iop.WorkspaceStatus
		code    iop.WorkspaceErrorCode
		message string
	}{
		{iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSPECIFIED, ""},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_READY, "workspace runtime not ready"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_UNSUPPORTED, "workspace cleanup unsupported"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_NOT_FOUND, "workspace request not found"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST, "workspace cleanup rejected"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_TIMEOUT, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_TIMEOUT, "workspace cleanup timed out"},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INTERNAL, "workspace cleanup failed"},
	}

	for _, tc := range cleanupValid {
		msg, ok := workspaceprotocol.CleanupTerminal(tc.status, tc.code)
		if !ok || msg != tc.message {
			t.Errorf("CleanupTerminal(%v, %v) = (%q, %v), want (%q, true)", tc.status, tc.code, msg, ok, tc.message)
		}
	}

	cleanupInvalid := []struct {
		status iop.WorkspaceStatus
		code   iop.WorkspaceErrorCode
	}{
		{iop.WorkspaceStatus_WORKSPACE_STATUS_SUCCESS, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INTERNAL},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_ERROR, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_CANCELLED},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_UNSUPPORTED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_CANCELLED, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_CANCELLED},
		{iop.WorkspaceStatus_WORKSPACE_STATUS_TIMEOUT, iop.WorkspaceErrorCode_WORKSPACE_ERROR_CODE_INVALID_REQUEST},
	}

	for _, tc := range cleanupInvalid {
		msg, ok := workspaceprotocol.CleanupTerminal(tc.status, tc.code)
		if ok {
			t.Errorf("CleanupTerminal(%v, %v) unexpectedly succeeded with %q", tc.status, tc.code, msg)
		}
	}
}
