package handlers

import (
	"io"
	"net/http"
	"strconv"
	"strings"

	"cmr-backend/internal/apperr"
	"cmr-backend/internal/httpx"
	"cmr-backend/internal/service"
)

type AdminPipelineHandler struct {
	service *service.AdminPipelineService
}

func NewAdminPipelineHandler(service *service.AdminPipelineService) *AdminPipelineHandler {
	return &AdminPipelineHandler{service: service}
}

func (h *AdminPipelineHandler) GetEventPipeline(w http.ResponseWriter, r *http.Request) {
	limit := 20
	if raw := r.URL.Query().Get("limit"); raw != "" {
		if parsed, err := strconv.Atoi(raw); err == nil {
			limit = parsed
		}
	}
	result, err := h.service.GetEventPipeline(r.Context(), r.PathValue("eventPublicID"), limit)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}
	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AdminPipelineHandler) BuildSource(w http.ResponseWriter, r *http.Request) {
	result, err := h.service.BuildSource(r.Context(), r.PathValue("sourceID"))
	if err != nil {
		httpx.WriteError(w, err)
		return
	}
	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AdminPipelineHandler) GetBuild(w http.ResponseWriter, r *http.Request) {
	result, err := h.service.GetBuild(r.Context(), r.PathValue("buildID"))
	if err != nil {
		httpx.WriteError(w, err)
		return
	}
	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AdminPipelineHandler) PublishBuild(w http.ResponseWriter, r *http.Request) {
	var req service.AdminPublishBuildInput
	if r.Body != nil {
		raw, err := io.ReadAll(r.Body)
		if err != nil {
			httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "failed to read request body: "+err.Error()))
			return
		}
		if len(raw) > 0 {
			r.Body = io.NopCloser(strings.NewReader(string(raw)))
			if err := httpx.DecodeJSON(r, &req); err != nil {
				httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body: "+err.Error()))
				return
			}
		}
	}

	result, err := h.service.PublishBuild(r.Context(), r.PathValue("buildID"), req)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}
	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AdminPipelineHandler) GetRelease(w http.ResponseWriter, r *http.Request) {
	result, err := h.service.GetRelease(r.Context(), r.PathValue("releasePublicID"))
	if err != nil {
		httpx.WriteError(w, err)
		return
	}
	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AdminPipelineHandler) BindReleaseRuntime(w http.ResponseWriter, r *http.Request) {
	var req service.AdminBindReleaseRuntimeInput
	if err := httpx.DecodeJSON(r, &req); err != nil {
		httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body: "+err.Error()))
		return
	}
	result, err := h.service.BindReleaseRuntime(r.Context(), r.PathValue("releasePublicID"), req)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}
	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AdminPipelineHandler) RollbackRelease(w http.ResponseWriter, r *http.Request) {
	var req service.AdminRollbackReleaseInput
	if err := httpx.DecodeJSON(r, &req); err != nil {
		httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body: "+err.Error()))
		return
	}
	result, err := h.service.RollbackRelease(r.Context(), r.PathValue("eventPublicID"), req)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}
	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}
