package converter

import (
	"time"

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

// WorkspaceMachine is implemented by workspace-domain machine views that can be
// converted to the central API DTO shape without converter importing the
// workspace domain package.
type WorkspaceMachine interface {
	WorkspaceMachineFields() WorkspaceMachineFields
}

// WorkspaceMachineFields carries the pure machine fields needed by ToMachine.
type WorkspaceMachineFields struct {
	ID                       string
	Name                     string
	Status                   string
	APIKeyPrefix             string
	CanManage                bool
	Hostname                 string
	OS                       string
	DaemonVersion            string
	Runtimes                 []string
	RuntimeDefaults          map[string]WorkspaceRuntimeDefaultsFields
	CreatedAt                time.Time
	CreatedByUserID          string
	DirectoryBrowseSupported bool
	DashboardSupported       bool
}

// WorkspaceRuntimeDefaultsFields carries runtime default fields needed by ToRuntimeDefaults.
type WorkspaceRuntimeDefaultsFields struct {
	Model           string
	ReasoningEffort string
}

// ToMachines converts workspace-domain machines to API DTO machines.
// Preserves the original workspace presenter behavior: empty input returns an empty (non-nil) slice.
func ToMachines[T WorkspaceMachine](machines []T) []dto.Machine {
	if len(machines) == 0 {
		return []dto.Machine{}
	}
	items := make([]dto.Machine, 0, len(machines))
	for _, machine := range machines {
		items = append(items, ToMachine(machine))
	}
	return items
}

// ToMachine converts one workspace-domain machine to its API DTO shape.
func ToMachine(machine WorkspaceMachine) dto.Machine {
	fields := machine.WorkspaceMachineFields()
	return dto.Machine{
		ID:                       fields.ID,
		Name:                     fields.Name,
		Status:                   fields.Status,
		APIKeyPrefix:             fields.APIKeyPrefix,
		CanManage:                fields.CanManage,
		Hostname:                 fields.Hostname,
		OS:                       fields.OS,
		DaemonVersion:            fields.DaemonVersion,
		Runtimes:                 ToRuntimeNames(fields.Runtimes),
		RuntimeDefaults:          ToRuntimeDefaults(fields.RuntimeDefaults),
		CreatedAt:                fields.CreatedAt,
		CreatedByUserID:          fields.CreatedByUserID,
		DirectoryBrowseSupported: fields.DirectoryBrowseSupported,
		DashboardSupported:       fields.DashboardSupported,
	}
}

// ToRuntimeNames converts runtime names to the API DTO runtime list.
// The machine API contract uses an empty JSON array, not null, when no runtimes are detected.
func ToRuntimeNames(runtimes []string) []string {
	if len(runtimes) == 0 {
		return []string{}
	}
	return append([]string{}, runtimes...)
}

// ToRuntimeDefaults converts workspace-domain runtime default values to API DTO runtime default values.
// The machine API contract uses an empty JSON object, not null, when no runtime defaults exist.
func ToRuntimeDefaults(defaults map[string]WorkspaceRuntimeDefaultsFields) map[string]dto.RuntimeDefaults {
	if len(defaults) == 0 {
		return map[string]dto.RuntimeDefaults{}
	}
	items := make(map[string]dto.RuntimeDefaults, len(defaults))
	for runtime, value := range defaults {
		items[runtime] = dto.RuntimeDefaults{Model: value.Model, ReasoningEffort: value.ReasoningEffort}
	}
	return items
}

// ToWorkspaceMemberResponse converts a store workspace member to its API DTO shape.
func ToWorkspaceMemberResponse(v workspace.WorkspaceMember) dto.WorkspaceMemberResponse {
	return dto.WorkspaceMemberResponse{
		UserID:           v.UserID,
		Email:            v.Email,
		Name:             v.Name,
		DisplayName:      v.DisplayName,
		MemberID:         v.MemberID,
		LegacyTargetKeys: v.LegacyTargetKeys,
		AvatarURL:        v.AvatarURL,
		Role:             v.Role,
		JoinedAt:         v.JoinedAt,
		AccessSources:    v.AccessSources,
		InChannel:        v.InChannel,
	}
}

// ToWorkspaceMemberResponses converts a slice of store workspace members to API DTOs.
func ToWorkspaceMemberResponses(items []workspace.WorkspaceMember) []dto.WorkspaceMemberResponse {
	if items == nil {
		return nil
	}
	out := make([]dto.WorkspaceMemberResponse, 0, len(items))
	for _, item := range items {
		out = append(out, ToWorkspaceMemberResponse(item))
	}
	return out
}

// ToWorkspaceMemberPageResponse converts a store workspace member page to its API DTO shape.
func ToWorkspaceMemberPageResponse(v workspace.WorkspaceMemberPage) dto.WorkspaceMemberPageResponse {
	return dto.WorkspaceMemberPageResponse{
		Members:    ToWorkspaceMemberResponses(v.Members),
		HasMore:    v.HasMore,
		NextCursor: v.NextCursor,
	}
}

// ToWorkspaceMemberOffboardingImpactResponse converts removal impact counts to API DTO shape.
func ToWorkspaceMemberOffboardingImpactResponse(v workspace.WorkspaceMemberOffboardingImpact) dto.WorkspaceMemberOffboardingImpactResponse {
	return dto.WorkspaceMemberOffboardingImpactResponse{
		MachineCount: v.MachineCount,
		AgentCount:   v.AgentCount,
	}
}

// ToWorkspaceInviteResponse converts a store workspace invite to its API DTO shape.
func ToWorkspaceInviteResponse(v workspace.WorkspaceInvite) dto.WorkspaceInviteResponse {
	return dto.WorkspaceInviteResponse{
		ID:                v.ID,
		InvitedEmail:      v.InvitedEmail,
		InvitedMobileHint: v.InvitedMobileHint,
		CreatedAt:         v.CreatedAt,
		InviteLink:        v.InviteLink,
	}
}

// ToWorkspaceInviteResponses converts a slice of store workspace invites to API DTOs.
func ToWorkspaceInviteResponses(items []workspace.WorkspaceInvite) []dto.WorkspaceInviteResponse {
	if items == nil {
		return nil
	}
	out := make([]dto.WorkspaceInviteResponse, 0, len(items))
	for _, item := range items {
		out = append(out, ToWorkspaceInviteResponse(item))
	}
	return out
}

func ToWorkspaceInvitePageResponse(page workspace.WorkspaceInvitePage) dto.WorkspaceInvitePageResponse {
	return dto.WorkspaceInvitePageResponse{
		Invites:    ToWorkspaceInviteResponses(page.Invites),
		HasMore:    page.HasMore,
		NextCursor: page.NextCursor,
	}
}
