package common

import (
	"bytes"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/base"
	collabent "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/ticket-manager/collaboration"
	engineerent "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/ticket-manager/engineer"
	taskent "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/ticket-manager/task"
	ticketent "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/ticket-manager/ticket"
	wsent "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/entity/ticket-manager/workspace"
)

func TestSetupPrinterRegistersTicketManagerTableSchemes(t *testing.T) {
	var output bytes.Buffer
	require.NoError(t, SetupPrinter("table", &output))

	now := time.Unix(100, 0).UTC()
	startedAt := int64(100)
	completedAt := int64(200)
	updatedAt := int64(300)
	resolvedAt := int64(400)

	cases := []struct {
		name  string
		value any
	}{
		{
			name: "workspace",
			value: wsent.Workspace{
				Updatable: base.Updatable{Base: base.Base{ID: 1, CreatedAt: startedAt}, UpdatedAt: &updatedAt},
				Name:      "workspace-a",
				Severity:  wsent.WorkspaceSeverityP1,
				Members: []wsent.WorkspaceMember{{
					Email: "owner@example.com",
					Role:  wsent.WorkspaceMemberRoleOwner,
					Group: "default",
				}},
				Status: wsent.WorkspaceStatusFiring,
			},
		},
		{
			name:  "issue binding",
			value: wsent.IssueBinding{Base: base.Base{ID: 2, CreatedAt: startedAt}, WorkspaceID: 1, IssueKey: "DM-1", BoundBy: "system"},
		},
		{
			name:  "alert binding",
			value: wsent.AlertBinding{Base: base.Base{ID: 3, CreatedAt: startedAt}, WorkspaceID: 1, AlertKey: "alert-1", BoundBy: "system"},
		},
		{
			name:  "tenant binding",
			value: wsent.TenantBinding{Base: base.Base{ID: 17, CreatedAt: startedAt}, WorkspaceID: 1, TenantID: "tenant-1", TenantName: "Tenant One", TenantRegion: "APAC"},
		},
		{
			name: "cluster binding",
			value: wsent.ClusterBinding{
				Base:            base.Base{ID: 18, CreatedAt: startedAt},
				WorkspaceID:     1,
				ClusterID:       "cluster-1",
				ClusterName:     "Cluster One",
				ClusterType:     "LOGICAL_CLUSTER",
				ClusterProvider: "aws",
				ClusterRegion:   "us-west-2",
			},
		},
		{
			name:  "collaboration resource binding",
			value: wsent.CollaborationResourceBinding{Base: base.Base{ID: 4, CreatedAt: startedAt}, WorkspaceID: 1, ResourceID: 10, BoundBy: "system"},
		},
		{
			name: "advice",
			value: wsent.Advice{
				Updatable:   base.Updatable{Base: base.Base{ID: 5, CreatedAt: startedAt}, UpdatedAt: &updatedAt},
				WorkspaceID: 1,
				Type:        wsent.AdivceTypeAddTask,
				Status:      wsent.AdviceStatusIgnored,
			},
		},
		{
			name: "ticket",
			value: ticketent.Ticket{
				ID:                6,
				JiraIssueKey:      "DM-2",
				Title:             "ticket title",
				CurrentJiraStatus: "Open",
				JiraAssignee:      "assignee@example.com",
				CreatedAt:         now,
				UpdatedAt:         now,
			},
		},
		{
			name: "jira issue",
			value: ticketent.JiraIssue{
				ID:         "10001",
				Key:        "DM-3",
				Summary:    "jira summary",
				Status:     "Open",
				Priority:   "High",
				Assignee:   &ticketent.JiraUser{Email: "assignee@example.com"},
				CreatedAt:  startedAt,
				UpdatedAt:  updatedAt,
				ResolvedAt: &resolvedAt,
			},
		},
		{
			name: "timeline event",
			value: ticketent.TimelineEvent{
				ID:         7,
				TicketID:   6,
				EventType:  "status_changed",
				OccurredAt: now,
				ActorType:  ticketent.ActorTypeHuman,
				ActorID:    "user@example.com",
				Source:     ticketent.SourceJira,
			},
		},
		{
			name:  "task list",
			value: taskent.TaskList{Updatable: base.Updatable{Base: base.Base{ID: 8, CreatedAt: startedAt}, UpdatedAt: &updatedAt}, Name: "task list", Owner: "owner@example.com"},
		},
		{
			name: "task",
			value: taskent.Task{
				Updatable:   base.Updatable{Base: base.Base{ID: 9, CreatedAt: startedAt}, UpdatedAt: &updatedAt},
				Title:       "task title",
				Priority:    taskent.TaskPriorityP1,
				Creator:     "creator@example.com",
				StartedAt:   &startedAt,
				CompletedAt: &completedAt,
				TaskListID:  8,
			},
		},
		{
			name: "collaboration resource",
			value: collabent.Resource{
				Base:       base.Base{ID: 10, CreatedAt: startedAt},
				Type:       collabent.TypeChat,
				Provider:   collabent.ProviderLark,
				ResourceID: "chat-id",
				Name:       "chat",
			},
		},
		{
			name: "workspace collaboration resource",
			value: wsent.CollaborationResource{
				CollaborationResourceBinding: wsent.CollaborationResourceBinding{
					Base:        base.Base{ID: 16, CreatedAt: startedAt},
					WorkspaceID: 1,
					ResourceID:  10,
					BoundBy:     "owner@example.com",
				},
				CollaborationResource: &collabent.Resource{
					Base:       base.Base{ID: 10, CreatedAt: startedAt},
					Type:       collabent.TypeChat,
					Provider:   collabent.ProviderLark,
					ResourceID: "chat-id",
					Name:       "chat",
					Link:       "https://example.com/chat",
				},
			},
		},
		{
			name: "engineer",
			value: engineerent.Engineer{
				Email:         "engineer@example.com",
				DispatchState: engineerent.DispatchState{DispatchEnabled: true},
				Availability:  engineerent.EngineerAvailability{IsOnCall: true},
			},
		},
	}

	for _, tt := range cases {
		t.Run(tt.name, func(t *testing.T) {
			output.Reset()
			require.NoError(t, Printer.PrintObject(tt.value))
			require.NotEmpty(t, output.String())
			if tt.name == "advice" {
				require.Contains(t, output.String(), "Status")
				require.Contains(t, output.String(), "ignored")
			}
		})
	}
}

func TestPrinterFormatsInt64TimestampsAsTime(t *testing.T) {
	local := time.Local
	time.Local = time.FixedZone("TEST", 8*3600)
	t.Cleanup(func() {
		time.Local = local
	})

	var output bytes.Buffer
	require.NoError(t, SetupPrinter("table", &output))

	startedAt := int64(946684800)
	archivedAt := int64(946688400)
	require.NoError(t, Printer.PrintObject(wsent.Workspace{
		Updatable:  base.Updatable{Base: base.Base{ID: 1}},
		Name:       "workspace-a",
		Severity:   wsent.WorkspaceSeverityP1,
		Status:     wsent.WorkspaceStatusFiring,
		StartedAt:  startedAt,
		ArchivedAt: &archivedAt,
		TaskListID: 1,
	}))

	result := output.String()
	require.Contains(t, result, "2000-01-01 08:00:00 TEST")
	require.Contains(t, result, "2000-01-01 09:00:00 TEST")
	require.NotContains(t, result, "946684800")
	require.NotContains(t, result, "946688400")
}
