package handlers

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

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

	"github.com/google/uuid"
)

type CaseHandler struct {
	svc *services.CaseService
}

func NewCaseHandler(svc *services.CaseService) *CaseHandler {
	return &CaseHandler{svc: svc}
}

func (h *CaseHandler) List(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
	limit, offset = clampPagination(limit, offset)

	search := r.URL.Query().Get("search")
	if msg := validateStringLength("search", search, maxSearchLen); msg != "" {
		writeError(w, http.StatusBadRequest, msg)
		return
	}

	filter := services.CaseFilter{
		Status: r.URL.Query().Get("status"),
		Type:   r.URL.Query().Get("type"),
		Search: search,
		Limit:  limit,
		Offset: offset,
	}

	cases, total, err := h.svc.List(r.Context(), tenantID, filter)
	if err != nil {
		internalError(w, "failed to list cases", err)
		return
	}

	writeJSON(w, http.StatusOK, map[string]interface{}{
		"cases": cases,
		"total": total,
	})
}

func (h *CaseHandler) Create(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}
	userID, _ := auth.UserFromContext(r.Context())

	var input services.CreateCaseInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid JSON body")
		return
	}
	if input.CaseNumber == "" || input.Title == "" {
		writeError(w, http.StatusBadRequest, "case_number and title are required")
		return
	}
	if msg := validateStringLength("case_number", input.CaseNumber, maxCaseNumberLen); msg != "" {
		writeError(w, http.StatusBadRequest, msg)
		return
	}
	if msg := validateStringLength("title", input.Title, maxTitleLen); msg != "" {
		writeError(w, http.StatusBadRequest, msg)
		return
	}

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

	writeJSON(w, http.StatusCreated, c)
}

func (h *CaseHandler) Get(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	caseID, err := uuid.Parse(r.PathValue("id"))
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid case ID")
		return
	}

	detail, err := h.svc.GetByID(r.Context(), tenantID, caseID)
	if err != nil {
		internalError(w, "failed to get case", err)
		return
	}
	if detail == nil {
		writeError(w, http.StatusNotFound, "case not found")
		return
	}

	writeJSON(w, http.StatusOK, detail)
}

func (h *CaseHandler) Update(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}
	userID, _ := auth.UserFromContext(r.Context())

	caseID, err := uuid.Parse(r.PathValue("id"))
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid case ID")
		return
	}

	var input services.UpdateCaseInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid JSON body")
		return
	}
	if input.Title != nil {
		if msg := validateStringLength("title", *input.Title, maxTitleLen); msg != "" {
			writeError(w, http.StatusBadRequest, msg)
			return
		}
	}
	if input.CaseNumber != nil {
		if msg := validateStringLength("case_number", *input.CaseNumber, maxCaseNumberLen); msg != "" {
			writeError(w, http.StatusBadRequest, msg)
			return
		}
	}

	updated, err := h.svc.Update(r.Context(), tenantID, caseID, userID, input)
	if err != nil {
		internalError(w, "failed to update case", err)
		return
	}
	if updated == nil {
		writeError(w, http.StatusNotFound, "case not found")
		return
	}

	writeJSON(w, http.StatusOK, updated)
}

func (h *CaseHandler) Delete(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}
	userID, _ := auth.UserFromContext(r.Context())

	caseID, err := uuid.Parse(r.PathValue("id"))
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid case ID")
		return
	}

	if err := h.svc.Delete(r.Context(), tenantID, caseID, userID); err != nil {
		writeError(w, http.StatusNotFound, "case not found")
		return
	}

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