package handlers

import (
	"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 InvoiceHandler struct {
	svc *services.InvoiceService
}

func NewInvoiceHandler(svc *services.InvoiceService) *InvoiceHandler {
	return &InvoiceHandler{svc: svc}
}

// List handles GET /api/invoices?case_id=&status=
func (h *InvoiceHandler) List(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	var caseID *uuid.UUID
	if caseStr := r.URL.Query().Get("case_id"); caseStr != "" {
		parsed, err := uuid.Parse(caseStr)
		if err != nil {
			writeError(w, http.StatusBadRequest, "invalid case_id")
			return
		}
		caseID = &parsed
	}

	invoices, err := h.svc.List(r.Context(), tenantID, caseID, r.URL.Query().Get("status"))
	if err != nil {
		internalError(w, "failed to list invoices", err)
		return
	}

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

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

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

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

	writeJSON(w, http.StatusOK, inv)
}

// Create handles POST /api/invoices
func (h *InvoiceHandler) 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.CreateInvoiceInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid JSON body")
		return
	}

	if input.ClientName == "" {
		writeError(w, http.StatusBadRequest, "client_name is required")
		return
	}
	if input.CaseID == uuid.Nil {
		writeError(w, http.StatusBadRequest, "case_id is required")
		return
	}

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

	writeJSON(w, http.StatusCreated, inv)
}

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

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

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

	inv, err := h.svc.Update(r.Context(), tenantID, invoiceID, input)
	if err != nil {
		writeError(w, http.StatusBadRequest, err.Error())
		return
	}

	writeJSON(w, http.StatusOK, inv)
}

// UpdateStatus handles PATCH /api/invoices/{id}/status
func (h *InvoiceHandler) UpdateStatus(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

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

	var body struct {
		Status string `json:"status"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, http.StatusBadRequest, "invalid JSON body")
		return
	}
	if body.Status == "" {
		writeError(w, http.StatusBadRequest, "status is required")
		return
	}

	inv, err := h.svc.UpdateStatus(r.Context(), tenantID, invoiceID, body.Status)
	if err != nil {
		writeError(w, http.StatusBadRequest, err.Error())
		return
	}

	writeJSON(w, http.StatusOK, inv)
}
