package handlers

import (
	"net/http"
	"strconv"

	"github.com/calendarapi/internal/middleware"
	"github.com/calendarapi/internal/models"
	"github.com/calendarapi/internal/service"
	"github.com/calendarapi/internal/utils"
	"github.com/go-chi/chi/v5"
)

type ContactHandler struct {
	contactSvc *service.ContactService
}

func NewContactHandler(contactSvc *service.ContactService) *ContactHandler {
	return &ContactHandler{contactSvc: contactSvc}
}

func (h *ContactHandler) List(w http.ResponseWriter, r *http.Request) {
	userID, _ := middleware.GetUserID(r.Context())
	q := r.URL.Query()

	var search *string
	if s := q.Get("search"); s != "" {
		search = &s
	}
	limit := 50
	if l := q.Get("limit"); l != "" {
		if v, err := strconv.Atoi(l); err == nil {
			limit = v
		}
	}

	contacts, cursor, err := h.contactSvc.List(r.Context(), userID, search, limit, q.Get("cursor"))
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	utils.WriteList(w, contacts, models.PageInfo{Limit: int(utils.ClampLimit(limit)), NextCursor: cursor})
}

func (h *ContactHandler) Create(w http.ResponseWriter, r *http.Request) {
	userID, _ := middleware.GetUserID(r.Context())

	var req struct {
		FirstName *string `json:"first_name"`
		LastName  *string `json:"last_name"`
		Email     *string `json:"email"`
		Phone     *string `json:"phone"`
		Company   *string `json:"company"`
		Notes     *string `json:"notes"`
	}
	if err := utils.DecodeJSON(r, &req); err != nil {
		utils.WriteError(w, err)
		return
	}

	contact, err := h.contactSvc.Create(r.Context(), userID, service.CreateContactRequest{
		FirstName: req.FirstName,
		LastName:  req.LastName,
		Email:     req.Email,
		Phone:     req.Phone,
		Company:   req.Company,
		Notes:     req.Notes,
	})
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	utils.WriteJSON(w, http.StatusOK, map[string]interface{}{"contact": contact})
}

func (h *ContactHandler) Get(w http.ResponseWriter, r *http.Request) {
	userID, _ := middleware.GetUserID(r.Context())
	contactID, err := utils.ValidateUUID(chi.URLParam(r, "id"))
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	contact, err := h.contactSvc.Get(r.Context(), userID, contactID)
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	utils.WriteJSON(w, http.StatusOK, map[string]interface{}{"contact": contact})
}

func (h *ContactHandler) Update(w http.ResponseWriter, r *http.Request) {
	userID, _ := middleware.GetUserID(r.Context())
	contactID, err := utils.ValidateUUID(chi.URLParam(r, "id"))
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	var req struct {
		FirstName *string `json:"first_name"`
		LastName  *string `json:"last_name"`
		Email     *string `json:"email"`
		Phone     *string `json:"phone"`
		Company   *string `json:"company"`
		Notes     *string `json:"notes"`
	}
	if err := utils.DecodeJSON(r, &req); err != nil {
		utils.WriteError(w, err)
		return
	}

	contact, err := h.contactSvc.Update(r.Context(), userID, contactID, service.UpdateContactRequest{
		FirstName: req.FirstName,
		LastName:  req.LastName,
		Email:     req.Email,
		Phone:     req.Phone,
		Company:   req.Company,
		Notes:     req.Notes,
	})
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	utils.WriteJSON(w, http.StatusOK, map[string]interface{}{"contact": contact})
}

func (h *ContactHandler) Delete(w http.ResponseWriter, r *http.Request) {
	userID, _ := middleware.GetUserID(r.Context())
	contactID, err := utils.ValidateUUID(chi.URLParam(r, "id"))
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	if err := h.contactSvc.Delete(r.Context(), userID, contactID); err != nil {
		utils.WriteError(w, err)
		return
	}

	utils.WriteOK(w)
}
