package channel

import (
	"net/http"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/api/dto/converter"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
	"github.com/tidbcloud/AgentTeam/internal/store/message"
)

// ListReviewFeedback handles GET /api/review/feedback?contextId=... and the
// GET /api/review-contexts/:reviewContextId/feedback route. contextId is the
// review context id.
func (h *ThreadHandler) ListReviewFeedback(r api.WorkspaceScopedRequest) (api.Response, error) {
	rc, err := h.loadReviewForFeedback(r)
	if err != nil {
		return api.Response{}, err
	}
	if h.appStore == nil {
		return api.Response{}, api.NewHTTPError(http.StatusInternalServerError, "Internal server error")
	}
	limit, err := parseOptionalLimit(r.Gin.Query("limit"), false)
	if err != nil {
		return api.Response{}, err
	}
	messages, err := h.appStore.ListReviewFeedbackForUser(r.Context(), r.UserID(), r.WorkspaceID(), rc, limit)
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(dto.ReviewFeedbackListResponse{Feedback: converter.ToReviewFeedbackMessages(messages)}), nil
}

// SubmitReviewFeedback handles POST /api/review/feedback and the legacy
// POST /api/review-contexts/:reviewContextId/feedback route.
func (h *ThreadHandler) SubmitReviewFeedback(r api.WorkspaceScopedJSON[dto.ReviewFeedbackSubmitRequest]) (api.Response, error) {
	rc, err := h.loadReviewForFeedback(r.WorkspaceScopedRequest, r.Body.ContextID)
	if err != nil {
		return api.Response{}, err
	}
	if h.appStore == nil {
		return api.Response{}, api.NewHTTPError(http.StatusInternalServerError, "Internal server error")
	}
	params := message.ReviewFeedbackBuildRequest{
		ClientMessageID:     strings.TrimSpace(r.Body.ClientMessageID),
		Locale:              reviewFeedbackRequestLocale(r.Body.Locale, r.Gin.GetHeader("Accept-Language")),
		Decision:            r.Body.Decision,
		Summary:             r.Body.Summary,
		Refs:                r.Body.Refs,
		Items:               reviewFeedbackItemInputs(r.Body.Items),
		SubmittedByMemberID: strings.TrimSpace(r.Workspace.MemberID),
	}
	appMessage, delivery, err := h.appStore.CreateReviewFeedbackForUser(r.Context(), r.User.User, r.WorkspaceID(), rc, params)
	if err != nil {
		return api.Response{}, err
	}
	if h.messageFanout != nil && !delivery.IdempotentReplay {
		h.messageFanout.EmitCommittedHumanMessage(r.Context(), r.WorkspaceID(), appMessage, delivery)
	}
	return api.OK(dto.ReviewFeedbackMessageResponse{Feedback: converter.ToReviewFeedbackMessage(appMessage)}), nil
}

// ResolveReviewFeedbackItem handles POST /api/review-contexts/:reviewContextId/feedback/:messageId/items/:itemId/resolve.
func (h *ThreadHandler) ResolveReviewFeedbackItem(r api.WorkspaceScopedRequest) (api.Response, error) {
	return h.setReviewFeedbackItemStatus(r, message.ReviewFeedbackStatusResolved)
}

// ReopenReviewFeedbackItem handles POST /api/review-contexts/:reviewContextId/feedback/:messageId/items/:itemId/reopen.
func (h *ThreadHandler) ReopenReviewFeedbackItem(r api.WorkspaceScopedRequest) (api.Response, error) {
	return h.setReviewFeedbackItemStatus(r, message.ReviewFeedbackStatusOpen)
}

func (h *ThreadHandler) UpdateReviewFeedbackItemStatus(r api.WorkspaceScopedJSON[dto.ReviewFeedbackStatusRequest]) (api.Response, error) {
	return h.setReviewFeedbackItemStatus(r.WorkspaceScopedRequest, r.Body.Status, r.Body.ContextID)
}

func (h *ThreadHandler) setReviewFeedbackItemStatus(r api.WorkspaceScopedRequest, status string, contextIDs ...string) (api.Response, error) {
	rc, err := h.loadReviewForFeedback(r, contextIDs...)
	if err != nil {
		return api.Response{}, err
	}
	if h.appStore == nil {
		return api.Response{}, api.NewHTTPError(http.StatusInternalServerError, "Internal server error")
	}
	messageID := strings.TrimSpace(r.Gin.Param("messageId"))
	if messageID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "messageId is required")
	}
	itemID := strings.TrimSpace(r.Gin.Param("itemId"))
	if itemID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "itemId is required")
	}
	appMessage, err := h.appStore.SetReviewFeedbackItemStatusForUser(r.Context(), r.User.User, r.WorkspaceID(), rc, messageID, itemID, status)
	if err != nil {
		return api.Response{}, err
	}
	if h.messageFanout != nil {
		h.messageFanout.EmitMessageUpdated(r.Context(), r.WorkspaceID(), appMessage)
	}
	return api.OK(dto.ReviewFeedbackMessageResponse{Feedback: converter.ToReviewFeedbackMessage(appMessage)}), nil
}

// loadReviewForFeedback resolves the review context by its id. contextId /
// reviewContextId is the review context id.
func (h *ThreadHandler) loadReviewForFeedback(r api.WorkspaceScopedRequest, explicitContextIDs ...string) (agent.ReviewContext, error) {
	if h.reviewStore == nil {
		return agent.ReviewContext{}, api.NewHTTPError(http.StatusInternalServerError, "Internal server error")
	}
	contextID := ""
	for _, candidate := range explicitContextIDs {
		if trimmed := strings.TrimSpace(candidate); trimmed != "" {
			contextID = trimmed
			break
		}
	}
	if contextID == "" {
		contextID = strings.TrimSpace(r.Gin.Param("reviewContextId"))
	}
	if contextID == "" {
		contextID = strings.TrimSpace(r.Gin.Query("contextId"))
	}
	if contextID == "" {
		return agent.ReviewContext{}, api.NewHTTPError(http.StatusBadRequest, "contextId is required")
	}
	rc, err := h.reviewStore.GetReviewContext(r.Context(), r.WorkspaceID(), contextID)
	if err != nil {
		return agent.ReviewContext{}, err
	}
	if rc == nil {
		return agent.ReviewContext{}, ErrNotFound
	}
	return *rc, nil
}

func reviewFeedbackRequestLocale(candidates ...string) string {
	for _, candidate := range candidates {
		if trimmed := strings.TrimSpace(candidate); trimmed != "" {
			return trimmed
		}
	}
	return ""
}

func reviewFeedbackItemInputs(items []dto.ReviewFeedbackItemRequest) []message.ReviewFeedbackItemInput {
	if len(items) == 0 {
		return nil
	}
	converted := make([]message.ReviewFeedbackItemInput, 0, len(items))
	for _, item := range items {
		converted = append(converted, message.ReviewFeedbackItemInput{
			ID:                item.ID,
			Type:              item.Type,
			Kind:              item.Kind,
			Path:              item.Path,
			OldPath:           item.OldPath,
			Side:              item.Side,
			OldLine:           item.OldLine,
			NewLine:           item.NewLine,
			StartLine:         item.StartLine,
			EndLine:           item.EndLine,
			HunkHeader:        item.HunkHeader,
			AnchorFingerprint: item.AnchorFingerprint,
			CodePreview:       item.CodePreview,
			Body:              item.Body,
			Anchor:            item.Anchor,
			Metadata:          item.Metadata,
		})
	}
	return converted
}
