package handlers

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

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

	"github.com/google/uuid"
)

type PartyHandler struct {
	svc *services.PartyService
}

func NewPartyHandler(svc *services.PartyService) *PartyHandler {
	return &PartyHandler{svc: svc}
}

func (h *PartyHandler) List(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
	}

	parties, err := h.svc.ListByCase(r.Context(), tenantID, caseID)
	if err != nil {
		internalError(w, "failed to list parties", err)
		return
	}

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

func (h *PartyHandler) 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())

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

	var input services.CreatePartyInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid JSON body")
		return
	}
	if input.Name == "" {
		writeError(w, http.StatusBadRequest, "name is required")
		return
	}

	if msg := validateStringLength("name", input.Name, maxTitleLen); msg != "" {
		writeError(w, http.StatusBadRequest, msg)
		return
	}

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

	writeJSON(w, http.StatusCreated, party)
}

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

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

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

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

	writeJSON(w, http.StatusOK, updated)
}

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

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

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

	w.WriteHeader(http.StatusNoContent)
}
