package handlers

import (
	"net/http"
	"time"

	"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 BookingHandler struct {
	bookingSvc *service.BookingService
}

func NewBookingHandler(bookingSvc *service.BookingService) *BookingHandler {
	return &BookingHandler{bookingSvc: bookingSvc}
}

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

	var req models.BookingConfig
	if err := utils.DecodeJSON(r, &req); err != nil {
		utils.WriteError(w, err)
		return
	}

	link, err := h.bookingSvc.CreateLink(r.Context(), userID, calID, req)
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	utils.WriteJSON(w, http.StatusOK, link)
}

func (h *BookingHandler) GetAvailability(w http.ResponseWriter, r *http.Request) {
	token := chi.URLParam(r, "token")
	q := r.URL.Query()

	startStr := q.Get("start")
	endStr := q.Get("end")
	if startStr == "" || endStr == "" {
		utils.WriteError(w, models.NewValidationError("start and end required"))
		return
	}

	start, err := time.Parse(time.RFC3339, startStr)
	if err != nil {
		utils.WriteError(w, models.NewValidationError("invalid start time"))
		return
	}
	end, err := time.Parse(time.RFC3339, endStr)
	if err != nil {
		utils.WriteError(w, models.NewValidationError("invalid end time"))
		return
	}

	result, err := h.bookingSvc.GetAvailability(r.Context(), token, start, end)
	if err != nil {
		utils.WriteError(w, err)
		return
	}

	utils.WriteJSON(w, http.StatusOK, result)
}

func (h *BookingHandler) Reserve(w http.ResponseWriter, r *http.Request) {
	token := chi.URLParam(r, "token")

	var req struct {
		Name      string    `json:"name"`
		Email     string    `json:"email"`
		SlotStart time.Time `json:"slot_start"`
		SlotEnd   time.Time `json:"slot_end"`
		Notes     *string   `json:"notes"`
	}
	if err := utils.DecodeJSON(r, &req); err != nil {
		utils.WriteError(w, err)
		return
	}

	event, err := h.bookingSvc.Reserve(r.Context(), token, req.Name, req.Email, req.SlotStart, req.SlotEnd, req.Notes)
	if err != nil {
		utils.WriteError(w, err)
		return
	}

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