package handlers

import (
	"encoding/json"
	"net/http"

	"mgit.msbls.de/m/KanzlAI-mGMT/internal/auth"
	"mgit.msbls.de/m/KanzlAI-mGMT/internal/services"
)

// DeadlineHandlers holds handlers for deadline CRUD endpoints
type DeadlineHandlers struct {
	deadlines *services.DeadlineService
}

// NewDeadlineHandlers creates deadline handlers
func NewDeadlineHandlers(ds *services.DeadlineService) *DeadlineHandlers {
	return &DeadlineHandlers{deadlines: ds}
}

// Get handles GET /api/deadlines/{deadlineID}
func (h *DeadlineHandlers) Get(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	deadlineID, err := parsePathUUID(r, "deadlineID")
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid deadline ID")
		return
	}

	deadline, err := h.deadlines.GetByID(tenantID, deadlineID)
	if err != nil {
		internalError(w, "failed to fetch deadline", err)
		return
	}
	if deadline == nil {
		writeError(w, http.StatusNotFound, "deadline not found")
		return
	}

	writeJSON(w, http.StatusOK, deadline)
}

// ListAll handles GET /api/deadlines
func (h *DeadlineHandlers) ListAll(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	deadlines, err := h.deadlines.ListAll(tenantID)
	if err != nil {
		internalError(w, "failed to list deadlines", err)
		return
	}

	writeJSON(w, http.StatusOK, deadlines)
}

// ListForCase handles GET /api/cases/{caseID}/deadlines
func (h *DeadlineHandlers) ListForCase(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
	}

	deadlines, err := h.deadlines.ListForCase(tenantID, caseID)
	if err != nil {
		internalError(w, "failed to list deadlines for case", err)
		return
	}

	writeJSON(w, http.StatusOK, deadlines)
}

// Create handles POST /api/cases/{caseID}/deadlines
func (h *DeadlineHandlers) Create(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 input services.CreateDeadlineInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid request body")
		return
	}
	input.CaseID = caseID

	if input.Title == "" || input.DueDate == "" {
		writeError(w, http.StatusBadRequest, "title and due_date are required")
		return
	}
	if msg := validateStringLength("title", input.Title, maxTitleLen); msg != "" {
		writeError(w, http.StatusBadRequest, msg)
		return
	}

	deadline, err := h.deadlines.Create(r.Context(), tenantID, input)
	if err != nil {
		internalError(w, "failed to create deadline", err)
		return
	}

	writeJSON(w, http.StatusCreated, deadline)
}

// Update handles PUT /api/deadlines/{deadlineID}
func (h *DeadlineHandlers) Update(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	deadlineID, err := parsePathUUID(r, "deadlineID")
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid deadline ID")
		return
	}

	var input services.UpdateDeadlineInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	deadline, err := h.deadlines.Update(r.Context(), tenantID, deadlineID, input)
	if err != nil {
		internalError(w, "failed to update deadline", err)
		return
	}
	if deadline == nil {
		writeError(w, http.StatusNotFound, "deadline not found")
		return
	}

	writeJSON(w, http.StatusOK, deadline)
}

// Complete handles PATCH /api/deadlines/{deadlineID}/complete
func (h *DeadlineHandlers) Complete(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	deadlineID, err := parsePathUUID(r, "deadlineID")
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid deadline ID")
		return
	}

	deadline, err := h.deadlines.Complete(r.Context(), tenantID, deadlineID)
	if err != nil {
		internalError(w, "failed to complete deadline", err)
		return
	}
	if deadline == nil {
		writeError(w, http.StatusNotFound, "deadline not found")
		return
	}

	writeJSON(w, http.StatusOK, deadline)
}

// Delete handles DELETE /api/deadlines/{deadlineID}
func (h *DeadlineHandlers) Delete(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	deadlineID, err := parsePathUUID(r, "deadlineID")
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid deadline ID")
		return
	}

	if err := h.deadlines.Delete(r.Context(), tenantID, deadlineID); err != nil {
		writeError(w, http.StatusNotFound, "deadline not found")
		return
	}

	writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
}
