package agent

import (
	"context"
	"encoding/json"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/core/domain"
)

type PrincipalType string

const (
	PrincipalTypeAgent PrincipalType = "agent"
)

type ServiceContext struct {
	RequestID      string         `json:"requestId,omitempty"`
	WorkspaceID    string         `json:"workspaceId"`
	Subject        SubjectContext `json:"subject"`
	InstallationID string         `json:"installationId,omitempty"`
	Scopes         []string       `json:"scopes,omitempty"`
}

type SubjectContext struct {
	PrincipalID   string        `json:"principalId"`
	PrincipalType PrincipalType `json:"principalType"`
	MemberID      string        `json:"memberId,omitempty"`
	DisplayName   string        `json:"displayName,omitempty"`
}

func NewAgentServiceContext(workspaceID string, agentID string, memberID string) ServiceContext {
	return ServiceContext{
		WorkspaceID: strings.TrimSpace(workspaceID),
		Subject: SubjectContext{
			PrincipalID:   strings.TrimSpace(agentID),
			PrincipalType: PrincipalTypeAgent,
			MemberID:      strings.TrimSpace(memberID),
		},
	}
}

// BoardRef identifies one task board for the agent API task port.
type BoardRef struct {
	ChannelID string `json:"channelId,omitempty"`
	Channel   string `json:"channel,omitempty"`
}

// TaskRef identifies one task by opaque id or board-local number.
type TaskRef struct {
	TaskID     string `json:"taskId,omitempty"`
	TaskNumber int64  `json:"taskNumber,omitempty"`
}

func parseTaskStatusFilter(value string) (string, error) {
	switch strings.ToLower(strings.TrimSpace(value)) {
	case "", "all":
		return "", nil
	case "todo":
		return "todo", nil
	case "in_progress":
		return "in_progress", nil
	case "in_review":
		return "in_review", nil
	case "done":
		return "done", nil
	default:
		return "", badRequest("invalid status")
	}
}

type TaskActor struct {
	Type string `json:"type"`
	ID   string `json:"id"`
	Name string `json:"name"`
}

type AuthorProfile struct {
	ActorType      string `json:"actorType"`
	PrincipalID    string `json:"principalId,omitempty"`
	MemberID       string `json:"memberId,omitempty"`
	TargetID       string `json:"targetId,omitempty"`
	DisplayName    string `json:"displayName"`
	AvatarURL      string `json:"avatarUrl,omitempty"`
	ServiceKind    string `json:"serviceKind,omitempty"`
	ServiceSlug    string `json:"serviceSlug,omitempty"`
	ServiceBuiltin bool   `json:"serviceBuiltin,omitempty"`
	Badge          string `json:"badge,omitempty"`
}

type ContributionSource struct {
	Kind      string `json:"kind,omitempty"`
	RefType   string `json:"refType,omitempty"`
	RefID     string `json:"refId,omitempty"`
	RunID     string `json:"runId,omitempty"`
	EventID   string `json:"eventId,omitempty"`
	EventType string `json:"eventType,omitempty"`
	Label     string `json:"label,omitempty"`
}

type TaskSourceThread struct {
	ThreadChannelID string `json:"threadChannelId,omitempty"`
	ParentChannelID string `json:"parentChannelId"`
	ParentMessageID string `json:"parentMessageId"`
	Ref             string `json:"ref,omitempty"`
}

type TaskFieldValue struct {
	OptionID string `json:"optionId,omitempty"`
	Key      string `json:"key,omitempty"`
	Label    string `json:"label,omitempty"`
	RawValue string `json:"rawValue,omitempty"`
	IsLegacy bool   `json:"isLegacy,omitempty"`
	IsNone   bool   `json:"isNone,omitempty"`
}

type TaskProgressSummary struct {
	Total int64 `json:"total"`
	Done  int64 `json:"done"`
}

// Task is the agent API task domain view returned by the task board adapter.
type Task struct {
	ID               string     `json:"id"`
	TaskScopeID      string     `json:"taskScopeId,omitempty"`
	ChannelID        string     `json:"channelId"`
	TaskNumber       int64      `json:"taskNumber"`
	Title            string     `json:"title"`
	Status           string     `json:"status"`
	Description      string     `json:"description,omitempty"`
	Kind             string     `json:"kind,omitempty"`
	Priority         string     `json:"priority,omitempty"`
	BlockedReason    string     `json:"blockedReason,omitempty"`
	LastActivityAt   *time.Time `json:"lastActivityAt,omitempty"`
	ArtifactCount    int64      `json:"artifactCount,omitempty"`
	ParentTaskRef    string     `json:"parentTaskRef,omitempty"`
	DiscussionCount  int64      `json:"discussionCount,omitempty"`

	AssigneeProfile    *AuthorProfile      `json:"assigneeProfile,omitempty"`
	KindField          *TaskFieldValue     `json:"kindField,omitempty"`
	PriorityField      *TaskFieldValue     `json:"priorityField,omitempty"`
	CheckpointProgress TaskProgressSummary `json:"checkpointProgress,omitempty"`
	SubtaskProgress    TaskProgressSummary `json:"subtaskProgress,omitempty"`

	CreatedAt time.Time `json:"createdAt"`

	CreatedByProfile *AuthorProfile `json:"createdByProfile,omitempty"`
	CreatedByType    string         `json:"createdByType"`
	CreatedByID      string         `json:"createdById"`
	CreatedByName    string         `json:"createdByName"`

	Source       *ContributionSource `json:"source,omitempty"`
	SourceThread *TaskSourceThread   `json:"sourceThread,omitempty"`
	AssignedAt   *time.Time          `json:"assignedAt,omitempty"`

	CompletedAt *time.Time `json:"completedAt,omitempty"`
}

type TaskView struct {
	TaskScopeID      string         `json:"taskScopeId,omitempty"`
	TaskNumber       int64          `json:"taskNumber"`
	Title            string         `json:"title"`
	Status           string         `json:"status"`
	AssigneeProfile  *AuthorProfile `json:"assigneeProfile,omitempty"`
	CreatedByProfile *AuthorProfile `json:"createdByProfile,omitempty"`
	CreatedByName    string         `json:"createdByName,omitempty"`
}

type CreatedTask struct {
	TaskScopeID string `json:"taskScopeId,omitempty"`
	TaskNumber  int64  `json:"taskNumber"`
	Title       string `json:"title"`
	Reused      bool   `json:"reused,omitempty"`
}

type ClaimResult struct {
	TaskNumber int64  `json:"taskNumber"`
	Success    bool   `json:"success"`
	Reason     string `json:"reason,omitempty"`
}

type TaskFieldOption struct {
	ID         string   `json:"id"`
	FieldKind  string   `json:"fieldKind,omitempty"`
	Key        string   `json:"key"`
	Label      string   `json:"label"`
	Aliases    []string `json:"aliases,omitempty"`
	Position   int64    `json:"position,omitempty"`
	IsActive   bool     `json:"isActive"`
	UsageCount int64    `json:"usageCount,omitempty"`
}

type TaskMemberOption struct {
	MemberID string `json:"memberId"`
	Type     string `json:"type"`
	UserID   string `json:"userId,omitempty"`
	AgentID  string `json:"agentId,omitempty"`
	Name     string `json:"name,omitempty"`
	Label    string `json:"label,omitempty"`
}

type ListTaskOptionsRequest struct {
	Context ServiceContext `json:"context"`
	Board   BoardRef       `json:"board"`
	Role    string         `json:"role,omitempty"`
	Query   string         `json:"query,omitempty"`
	Limit   int            `json:"limit,omitempty"`
	Cursor  string         `json:"cursor,omitempty"`
}

type ListTaskOptionsResponse struct {
	PriorityOptions []TaskFieldOption  `json:"priorityOptions,omitempty"`
	KindOptions     []TaskFieldOption  `json:"kindOptions,omitempty"`
	AssigneeOptions []TaskMemberOption `json:"assigneeOptions,omitempty"`
	Limit           int                `json:"limit,omitempty"`
	HasMore         bool               `json:"has_more,omitempty"`
	NextCursor      string             `json:"next_cursor,omitempty"`
}

type TaskChecklistItem struct {
	ID      string `json:"id,omitempty"`
	Text    string `json:"text"`
	Checked bool   `json:"checked,omitempty"`
}

type TaskArtifact struct {
	ID               string          `json:"id"`
	Kind             string          `json:"kind"`
	Title            string          `json:"title,omitempty"`
	Payload          json.RawMessage `json:"payload,omitempty"`
	CreatedByProfile *AuthorProfile  `json:"createdByProfile,omitempty"`
	CreatedByRef     string          `json:"createdByRef,omitempty"`
	CreatedAt        time.Time       `json:"createdAt"`
}

type TaskActivityEvent struct {
	ID            string              `json:"id"`
	Type          string              `json:"type"`
	AuthorProfile *AuthorProfile      `json:"authorProfile,omitempty"`
	Source        *ContributionSource `json:"source,omitempty"`
	// ActorRef, ActorDisplayName, and SourceKind/Source* are retained only as
	// agent task API compatibility fields. Canonical task activity identity and
	// provenance are AuthorProfile and Source.
	ActorRef         string    `json:"actorRef,omitempty"`
	ActorDisplayName string    `json:"actorDisplayName,omitempty"`
	Payload          string    `json:"payload,omitempty"`
	SourceKind       string    `json:"sourceKind,omitempty"`
	SourceMessageID  string    `json:"sourceMessageId,omitempty"`
	SourceActivityID string    `json:"sourceActivityId,omitempty"`
	CreatedAt        time.Time `json:"createdAt"`
}

type TaskDiscussionEntry struct {
	ID            string              `json:"id"`
	TaskID        string              `json:"taskId"`
	Body          string              `json:"body"`
	AuthorProfile *AuthorProfile      `json:"authorProfile"`
	Source        *ContributionSource `json:"source,omitempty"`
	// CreatedBy is retained only as an agent task API compatibility adapter;
	// canonical task discussion identity is AuthorProfile.
	CreatedBy   TaskActor                  `json:"createdBy"`
	Attachments []TaskDiscussionAttachment `json:"attachments,omitempty"`
	CreatedAt   time.Time                  `json:"createdAt"`
}

type TaskDiscussionAttachment struct {
	ID           string `json:"id"`
	Filename     string `json:"filename"`
	ContentType  string `json:"contentType,omitempty"`
	SizeBytes    int64  `json:"sizeBytes,omitempty"`
	ThumbnailURL string `json:"thumbnailUrl,omitempty"`
}

type TaskTimelineEntry struct {
	ID         string               `json:"id"`
	Kind       string               `json:"kind"`
	CreatedAt  time.Time            `json:"createdAt"`
	Activity   *TaskActivityEvent   `json:"activity,omitempty"`
	Discussion *TaskDiscussionEntry `json:"discussion,omitempty"`
}

type TaskDetail struct {
	Task                     Task                `json:"task"`
	ParentTask               *Task               `json:"parentTask,omitempty"`
	Checkpoints              []TaskChecklistItem `json:"checkpoints,omitempty"`
	Timeline                 []TaskTimelineEntry `json:"timeline,omitempty"`
	TimelineHasMore          bool                `json:"timelineHasMore,omitempty"`
	TimelineNextCursor       string              `json:"timelineNextCursor,omitempty"`
	AcceptanceCriteria       []TaskChecklistItem `json:"acceptanceCriteria,omitempty"`
	ReviewChecklist          []TaskChecklistItem `json:"reviewChecklist,omitempty"`
	Subtasks                 []Task              `json:"subtasks,omitempty"`
	PinnedMessageRefs        []string            `json:"pinnedMessageRefs,omitempty"`
	PinnedMessageRefsHasMore bool                `json:"pinnedMessageRefsHasMore,omitempty"`
	RelevantURLs             []string            `json:"relevantURLs,omitempty"`
	RelevantURLsHasMore      bool                `json:"relevantURLsHasMore,omitempty"`
	WorkspaceRefs            []string            `json:"workspaceRefs,omitempty"`
	WorkspaceRefsHasMore     bool                `json:"workspaceRefsHasMore,omitempty"`
	Artifacts                []TaskArtifact      `json:"artifacts,omitempty"`
}

type TaskCreateInput struct {
	Title            string `json:"title,omitempty"`
	Description      string `json:"description,omitempty"`
	Kind             string `json:"kind,omitempty"`
	Priority         string `json:"priority,omitempty"`
	KindOptionID     string `json:"kindOptionId,omitempty"`
	PriorityOptionID string `json:"priorityOptionId,omitempty"`
	AssigneeRef      string `json:"assigneeRef,omitempty"`
}

type CreateTaskMetadata struct {
	SourceThreadChannelID       string `json:"sourceThreadChannelId,omitempty"`
	SourceThreadParentChannelID string `json:"sourceThreadParentChannelId,omitempty"`
	SourceThreadParentMessageID string `json:"sourceThreadParentMessageId,omitempty"`
	SourceThreadRef             string `json:"sourceThreadRef,omitempty"`
}

type CreateTasksRequest struct {
	Context  ServiceContext      `json:"context"`
	Board    BoardRef            `json:"board"`
	Titles   []string            `json:"titles"`
	Task     *TaskCreateInput    `json:"task,omitempty"`
	Metadata *CreateTaskMetadata `json:"metadata,omitempty"`
}

type CreateTasksResponse struct {
	ChannelID    string        `json:"channelId,omitempty"`
	Tasks        []Task        `json:"tasks,omitempty"`
	CreatedTasks []CreatedTask `json:"createdTasks,omitempty"`
}

type CreateSubtasksRequest struct {
	Context         ServiceContext            `json:"context"`
	Board           BoardRef                  `json:"board"`
	Task            TaskRef                   `json:"task"`
	ParentTaskScope *domain.MessageScopeValue `json:"parentTaskScope,omitempty"`
	SourceChannelID string                    `json:"sourceChannelId,omitempty"`
	Metadata        *CreateTaskMetadata       `json:"metadata,omitempty"`
	Titles          []string                  `json:"titles"`
	Input           *TaskCreateInput          `json:"input,omitempty"`
}

type CreateSubtasksResponse struct {
	ChannelID    string        `json:"channelId,omitempty"`
	Tasks        []Task        `json:"tasks,omitempty"`
	CreatedTasks []CreatedTask `json:"createdTasks,omitempty"`
}

type ListTasksRequest struct {
	Context         ServiceContext `json:"context"`
	Board           BoardRef       `json:"board"`
	Status          string         `json:"status,omitempty"`
	IncludeSubtasks bool           `json:"includeSubtasks,omitempty"`
	Limit           int            `json:"limit,omitempty"`
	Cursor          string         `json:"cursor,omitempty"`
	SearchQuery     string         `json:"searchQuery,omitempty"`
	SortMode        string         `json:"sortMode,omitempty"`
	QuickFilters    []string       `json:"quickFilters,omitempty"`
}

type ListTasksResponse struct {
	ChannelID  string     `json:"channelId,omitempty"`
	Tasks      []Task     `json:"tasks,omitempty"`
	TaskViews  []TaskView `json:"taskViews,omitempty"`
	Limit      int        `json:"limit,omitempty"`
	TotalCount int64      `json:"totalCount,omitempty"`
	HasMore    bool       `json:"hasMore,omitempty"`
	NextCursor string     `json:"nextCursor,omitempty"`
}

type ClaimTasksRequest struct {
	Context ServiceContext `json:"context"`
	Board   BoardRef       `json:"board"`
	Tasks   []TaskRef      `json:"tasks"`
}

type ClaimTasksResponse struct {
	ChannelID          string        `json:"channelId,omitempty"`
	Task               Task          `json:"task,omitempty"`
	Tasks              []Task        `json:"tasks,omitempty"`
	Results            []ClaimResult `json:"results,omitempty"`
	ChangedTaskNumbers []int64       `json:"changedTaskNumbers,omitempty"`
}

type UnclaimTaskRequest struct {
	Context ServiceContext `json:"context"`
	Board   BoardRef       `json:"board"`
	Task    TaskRef        `json:"task"`
}

type UnclaimTaskResponse struct {
	Task Task `json:"task"`
}

type TaskBlockInput struct {
	Reason string `json:"reason"`
}

type BlockTaskRequest struct {
	Context ServiceContext `json:"context"`
	Board   BoardRef       `json:"board"`
	Task    TaskRef        `json:"task"`
	Block   TaskBlockInput `json:"block"`
}

type BlockTaskResponse struct {
	Task    Task `json:"task"`
	Changed bool `json:"changed"`
}

type UnblockTaskRequest struct {
	Context ServiceContext `json:"context"`
	Board   BoardRef       `json:"board"`
	Task    TaskRef        `json:"task"`
}

type UnblockTaskResponse struct {
	Task    Task `json:"task"`
	Changed bool `json:"changed"`
}

type GetTaskDetailRequest struct {
	Context ServiceContext `json:"context"`
	Board   BoardRef       `json:"board"`
	Task    TaskRef        `json:"task"`
}

type GetTaskDetailResponse struct {
	Detail TaskDetail `json:"detail"`
}

type TaskUpdatePatch struct {
	Title              *string             `json:"title,omitempty"`
	Description        *string             `json:"description,omitempty"`
	Kind               *string             `json:"kind,omitempty"`
	Priority           *string             `json:"priority,omitempty"`
	KindOptionID       *string             `json:"kindOptionId,omitempty"`
	PriorityOptionID   *string             `json:"priorityOptionId,omitempty"`
	AssigneeRef        *string             `json:"assigneeRef,omitempty"`
	AcceptanceCriteria []TaskChecklistItem `json:"acceptanceCriteria,omitempty"`
	ReviewChecklist    []TaskChecklistItem `json:"reviewChecklist,omitempty"`
	PinnedMessageRefs  []string            `json:"pinnedMessageRefs,omitempty"`
	RelevantURLs       []string            `json:"relevantURLs,omitempty"`
	WorkspaceRefs      []string            `json:"workspaceRefs,omitempty"`
	BlockedReason      *string             `json:"blockedReason,omitempty"`
	ParentTaskRef      *string             `json:"parentTaskRef,omitempty"`
	AttachmentIDs      []string            `json:"attachmentIds,omitempty"`
}

type UpdateTaskRequest struct {
	Context ServiceContext  `json:"context"`
	Board   BoardRef        `json:"board"`
	Task    TaskRef         `json:"task"`
	Patch   TaskUpdatePatch `json:"patch"`
}

type UpdateTaskResponse struct {
	Task Task `json:"task"`
}

type UpdateTaskStatusRequest struct {
	Context ServiceContext `json:"context"`
	Board   BoardRef       `json:"board"`
	Task    TaskRef        `json:"task"`
	Status  string         `json:"status"`
}

type UpdateTaskStatusResponse struct {
	Task    Task `json:"task"`
	Changed bool `json:"changed"`
}

type TaskCheckpointInput struct {
	Text string `json:"text"`
}

type AddTaskCheckpointRequest struct {
	Context    ServiceContext      `json:"context"`
	Board      BoardRef            `json:"board"`
	Task       TaskRef             `json:"task"`
	Checkpoint TaskCheckpointInput `json:"checkpoint"`
}

type AddTaskCheckpointResponse struct {
	Task Task `json:"task"`
}

type DeleteTaskSubtaskMode string

const (
	DeleteTaskSubtaskModePromote DeleteTaskSubtaskMode = "promote"
	DeleteTaskSubtaskModeDelete  DeleteTaskSubtaskMode = "delete"
)

type DeleteTaskRequest struct {
	Context     ServiceContext
	Board       BoardRef
	Task        TaskRef
	SubtaskMode DeleteTaskSubtaskMode
}

type DeleteTaskResponse struct {
	DeletedTaskNumbers  []int64
	PromotedTaskNumbers []int64
}

type TaskBoardService interface {
	ListTasks(ctx context.Context, request ListTasksRequest) (ListTasksResponse, error)
	ListTaskOptions(ctx context.Context, request ListTaskOptionsRequest) (ListTaskOptionsResponse, error)
	CreateTasks(ctx context.Context, request CreateTasksRequest) (CreateTasksResponse, error)
	CreateSubtasks(ctx context.Context, request CreateSubtasksRequest) (CreateSubtasksResponse, error)
	ClaimTasks(ctx context.Context, request ClaimTasksRequest) (ClaimTasksResponse, error)
	UnclaimTask(ctx context.Context, request UnclaimTaskRequest) (UnclaimTaskResponse, error)
	BlockTask(ctx context.Context, request BlockTaskRequest) (BlockTaskResponse, error)
	UnblockTask(ctx context.Context, request UnblockTaskRequest) (UnblockTaskResponse, error)
	GetTaskDetail(ctx context.Context, request GetTaskDetailRequest) (GetTaskDetailResponse, error)
	UpdateTask(ctx context.Context, request UpdateTaskRequest) (UpdateTaskResponse, error)
	UpdateTaskStatus(ctx context.Context, request UpdateTaskStatusRequest) (UpdateTaskStatusResponse, error)
	AddTaskCheckpoint(ctx context.Context, request AddTaskCheckpointRequest) (AddTaskCheckpointResponse, error)
	DeleteTask(ctx context.Context, request DeleteTaskRequest) (DeleteTaskResponse, error)
}
