package task

import (
	"log/slog"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/store/taskboard"
	"github.com/tidbcloud/AgentTeam/internal/unread"
)

type taskHandlerBase struct {
	taskBoard                 TaskBoardService
	unreadRuntime             TaskUnreadRuntime
	conversationReadProjector TaskConversationReadProjector
	logger                    *slog.Logger
}

// ParityHandler owns task-facing parity facade routes.
type ParityHandler struct {
	taskBoard                   TaskParityBoard
	store                       TaskParityStore
	fanout                      MessageFanout
	unreadRuntime               TaskUnreadRuntime
	conversationPolicyProjector TaskConversationPolicyProjector
	logger                      *slog.Logger
}

// BoardOptionHandler owns task board field option routes.
type BoardOptionHandler struct {
	taskHandlerBase
}

// BoardViewStateHandler owns task board view state routes.
type BoardViewStateHandler struct {
	taskHandlerBase
}

// BrowseHandler owns task browse routes.
type BrowseHandler struct {
	taskHandlerBase
}

// CollectionHandler owns task collection listing and creation routes.
type CollectionHandler struct {
	taskHandlerBase
}

// DetailHandler owns task detail, activity, update, and delete routes.
type DetailHandler struct {
	taskHandlerBase
}

// LifecycleHandler owns task assignment and status transition routes.
type LifecycleHandler struct {
	taskHandlerBase
}

// SubtaskHandler owns subtask creation routes.
type SubtaskHandler struct {
	taskHandlerBase
}

// CheckpointHandler owns task checkpoint routes.
type CheckpointHandler struct {
	taskHandlerBase
}

// CollaboratorHandler owns task/thread/channel collaborator list routes.
type CollaboratorHandler struct {
	collaborators TaskCollaboratorBoard
}

type routeHandlers struct {
	boardOptions         *BoardOptionHandler
	boardView            *BoardViewStateHandler
	browse               *BrowseHandler
	collection           *CollectionHandler
	detail               *DetailHandler
	lifecycle            *LifecycleHandler
	subtasks             *SubtaskHandler
	checkpoints          *CheckpointHandler
	collaborators        *CollaboratorHandler
	collaboratorRequests *CollaboratorRequestHandler
	parity               *ParityHandler
}

func newRouteHandlers(dependencies Dependencies) routeHandlers {
	rawBoard := dependencies.TaskBoard
	base := taskHandlerBase{
		taskBoard:                 NewTaskBoardServiceAdapter(rawBoard),
		unreadRuntime:             dependencies.UnreadRuntime,
		conversationReadProjector: dependencies.ConversationReadProjector,
		logger:                    dependencies.Logger,
	}
	return routeHandlers{
		boardOptions:         &BoardOptionHandler{taskHandlerBase: base},
		boardView:            &BoardViewStateHandler{taskHandlerBase: base},
		browse:               &BrowseHandler{taskHandlerBase: base},
		collection:           &CollectionHandler{taskHandlerBase: base},
		detail:               &DetailHandler{taskHandlerBase: base},
		lifecycle:            &LifecycleHandler{taskHandlerBase: base},
		subtasks:             &SubtaskHandler{taskHandlerBase: base},
		checkpoints:          &CheckpointHandler{taskHandlerBase: base},
		collaborators:        &CollaboratorHandler{collaborators: taskCollaboratorBoard(rawBoard)},
		collaboratorRequests: &CollaboratorRequestHandler{service: dependencies.CollaboratorRequests},
		parity:               &ParityHandler{taskBoard: rawBoard, store: dependencies.Store, fanout: dependencies.MessageFanout, unreadRuntime: dependencies.UnreadRuntime, conversationPolicyProjector: dependencies.ConversationPolicyProjector, logger: dependencies.Logger},
	}
}

func (handler taskHandlerBase) applyTaskScopeInvalidated(workspaceID string, memberID string, task Task) {
	scopeID := strings.TrimSpace(task.TaskScopeID)
	if scopeID == "" {
		return
	}
	applyTaskScopeInvalidatedEvent(handler.unreadRuntime, workspaceID, memberID, scopeID, "task_scope_policy")
}

func (handler *ParityHandler) applyTaskScopeInvalidated(workspaceID string, memberID string, task taskboard.Task) {
	scopeID := strings.TrimSpace(task.TaskScopeID)
	if scopeID == "" {
		return
	}
	applyTaskScopeInvalidatedEvent(handler.unreadRuntime, workspaceID, memberID, scopeID, "task_scope_policy")
}

func applyTaskScopeInvalidatedEvent(runtime TaskUnreadRuntime, workspaceID string, memberID string, scopeID string, reason string) {
	if runtime == nil {
		return
	}
	event := unread.ScopeInvalidated{
		WorkspaceID: strings.TrimSpace(workspaceID),
		ScopeID:     strings.TrimSpace(scopeID),
		Reason:      strings.TrimSpace(reason),
	}
	if memberID = strings.TrimSpace(memberID); memberID != "" {
		event.MemberIDs = []string{memberID}
	}
	_ = runtime.ApplyScopeInvalidated(event)
}

func applyTaskReadCursors(runtime TaskUnreadRuntime, workspaceID string, memberID string, task Task, readState TaskReadState) {
	if runtime == nil {
		return
	}
	scopeID := strings.TrimSpace(task.TaskScopeID)
	if scopeID == "" {
		return
	}
	memberID = strings.TrimSpace(memberID)
	if memberID == "" {
		return
	}
	_ = runtime.ApplyReadCursor(unread.ReadCursorAdvanced{
		WorkspaceID:                 strings.TrimSpace(workspaceID),
		MemberID:                    memberID,
		ScopeID:                     scopeID,
		LastReadSeq:                 readState.LastMessageReadSeq,
		ManualUnreadGeneration:      readState.ManualUnreadGeneration,
		ManualUnreadGenerationKnown: true,
	})
	_ = runtime.ApplyActivityReadCursor(unread.ActivityReadCursorAdvanced{
		WorkspaceID: strings.TrimSpace(workspaceID),
		MemberID:    memberID,
		ScopeID:     scopeID,
		LastReadSeq: readState.LastActivityReadSeq,
	})
}
