package handlers import ( "encoding/json" "net/http" "github.com/google/uuid" "mgit.msbls.de/m/KanzlAI-mGMT/internal/auth" "mgit.msbls.de/m/KanzlAI-mGMT/internal/services" ) // DetermineHandlers holds handlers for deadline determination endpoints type DetermineHandlers struct { determine *services.DetermineService deadlines *services.DeadlineService } // NewDetermineHandlers creates determine handlers func NewDetermineHandlers(determine *services.DetermineService, deadlines *services.DeadlineService) *DetermineHandlers { return &DetermineHandlers{determine: determine, deadlines: deadlines} } // GetTimeline handles GET /api/proceeding-types/{code}/timeline // Returns the full event tree for a proceeding type (no date calculations) func (h *DetermineHandlers) GetTimeline(w http.ResponseWriter, r *http.Request) { code := r.PathValue("code") if code == "" { writeError(w, http.StatusBadRequest, "proceeding type code required") return } timeline, pt, err := h.determine.GetTimeline(code) if err != nil { writeError(w, http.StatusNotFound, "proceeding type not found") return } writeJSON(w, http.StatusOK, map[string]any{ "proceeding_type": pt, "timeline": timeline, }) } // Determine handles POST /api/deadlines/determine // Calculates the full timeline with cascading dates and conditional logic func (h *DetermineHandlers) Determine(w http.ResponseWriter, r *http.Request) { var req services.DetermineRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if req.ProceedingType == "" || req.TriggerEventDate == "" { writeError(w, http.StatusBadRequest, "proceeding_type and trigger_event_date are required") return } resp, err := h.determine.Determine(req) if err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, resp) } // BatchCreate handles POST /api/cases/{caseID}/deadlines/batch // Creates multiple deadlines on a case from determined timeline func (h *DetermineHandlers) BatchCreate(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusForbidden, "missing tenant") return } caseID, err := parsePathUUID(r, "caseID") if err != nil { writeError(w, http.StatusBadRequest, "invalid case ID") return } var req struct { Deadlines []struct { Title string `json:"title"` DueDate string `json:"due_date"` OriginalDueDate *string `json:"original_due_date,omitempty"` RuleID *uuid.UUID `json:"rule_id,omitempty"` RuleCode *string `json:"rule_code,omitempty"` Notes *string `json:"notes,omitempty"` } `json:"deadlines"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if len(req.Deadlines) == 0 { writeError(w, http.StatusBadRequest, "at least one deadline is required") return } var created int for _, d := range req.Deadlines { if d.Title == "" || d.DueDate == "" { continue } input := services.CreateDeadlineInput{ CaseID: caseID, Title: d.Title, DueDate: d.DueDate, Source: "determined", RuleID: d.RuleID, Notes: d.Notes, } _, err := h.deadlines.Create(r.Context(), tenantID, input) if err != nil { internalError(w, "failed to create deadline", err) return } created++ } writeJSON(w, http.StatusCreated, map[string]any{ "created": created, }) }