package run

import (
	"net/http"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/workflow/calendar"
)

type CalendarHandler struct{ service CalendarService }

func NewCalendarHandler(service CalendarService) *CalendarHandler {
	return &CalendarHandler{service: service}
}

// List handles GET /api/v1/workspaces/:workspaceId/workflow/calendar.
// It returns accepted Runs and not-yet-accepted Schedule occurrences in the
// requested half-open [from, to) window.
func (handler *CalendarHandler) List(r api.WorkspaceScopedRequest) (api.Response, error) {
	from, err := calendarQueryTime(r.Gin.Query("from"), "from")
	if err != nil {
		return api.Response{}, err
	}
	to, err := calendarQueryTime(r.Gin.Query("to"), "to")
	if err != nil {
		return api.Response{}, err
	}
	result, err := handler.service.List(r.Context(), calendar.ListInput{
		WorkspaceID: r.WorkspaceID(), From: from, To: to,
	})
	if err != nil {
		return api.Response{}, err
	}
	items := make([]dto.WorkflowCalendarItem, 0, len(result.Items))
	for _, item := range result.Items {
		items = append(items, calendarItemResponse(item))
	}
	return api.OK(dto.WorkflowCalendarResponse{From: result.From, To: result.To, Items: items}), nil
}

func calendarQueryTime(value, name string) (time.Time, error) {
	value = strings.TrimSpace(value)
	if value == "" {
		return time.Time{}, api.NewHTTPErrorWithCode(
			http.StatusBadRequest, name+" is required", string(calendar.ErrorCodeInvalidWindow),
		)
	}
	parsed, err := time.Parse(time.RFC3339, value)
	if err != nil {
		return time.Time{}, api.NewHTTPErrorWithCode(
			http.StatusBadRequest, name+" must be RFC3339", string(calendar.ErrorCodeInvalidWindow),
		)
	}
	return parsed, nil
}

func calendarItemResponse(item calendar.Item) dto.WorkflowCalendarItem {
	response := dto.WorkflowCalendarItem{
		Kind: item.Kind, OccursAt: item.OccursAt,
		Workflow: dto.WorkflowCalendarWorkflow{
			PlanID: item.Workflow.PlanID, PlanVersionID: item.Workflow.PlanVersionID,
			Key: item.Workflow.Key, DisplayName: item.Workflow.DisplayName,
		},
	}
	if item.Schedule != nil {
		response.Schedule = &dto.WorkflowCalendarSchedule{
			BindingID: item.Schedule.BindingID, BindingRevisionID: item.Schedule.BindingRevisionID,
			BindingSourceID: item.Schedule.BindingSourceID, BindingKey: item.Schedule.BindingKey,
			BindingDisplayName: item.Schedule.BindingDisplayName,
			OccurrenceKey:      item.Schedule.OccurrenceKey,
		}
	}
	if item.Run != nil {
		response.Run = &dto.WorkflowCalendarRun{
			ID: item.Run.ID, InvocationID: item.Run.InvocationID, Status: item.Run.Status,
			QueuedAt: item.Run.QueuedAt, StartedAt: item.Run.StartedAt,
			CompletedAt: item.Run.CompletedAt, CanceledAt: item.Run.CanceledAt,
		}
	}
	return response
}
