package opsapi

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/tidbcloud/observability/pkg/common/message"
	"github.com/tidbcloud/observability/pkg/opsservice"
	"github.com/tidbcloud/observability/pkg/regionalapi/apiinterceptor"
)

// CreateUpgradeOperation
// @Summary Create an upgrade operation
// @Description Creates a new Kubernetes cluster upgrade operation with step-based execution
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param request body message.CreateClusterUpgradeReq true "create cluster upgrade request"
// @Success 202 {object} message.Result{data=message.CreateClusterUpgradeResp}
// @Failure 400 {object} message.Result
// @Failure 500 {object} message.Result
// @Router /upgradeOperations [post]
func CreateUpgradeOperation(c *gin.Context) {
	req := &message.CreateClusterUpgradeReq{}
	if ok := apiinterceptor.HandleJsonRequestFromBody(c, req); ok {
		resp, err := opsservice.GetUpgradeOpService().CreateUpgrade(c, *req)
		if err != nil {
			apiinterceptor.Fail(c, err)
		} else {
			apiinterceptor.Succeed(c, http.StatusAccepted, resp)
		}
	}
}

// ListUpgradeOperations
// @Summary List upgrade operations
// @Description Lists all cluster upgrade operations with optional filtering
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param request query message.ListClusterUpgradesReq true "list cluster upgrades request"
// @Success 200 {object} message.Result{data=message.ListClusterUpgradesResp}
// @Failure 500 {object} message.Result
// @Router /upgradeOperations [get]
func ListUpgradeOperations(c *gin.Context) {
	req := &message.ListClusterUpgradesReq{}
	if ok := apiinterceptor.HandleJsonRequestFromQuery(c, req); ok {
		resp, err := opsservice.GetUpgradeOpService().ListUpgrades(c, *req)
		if err != nil {
			apiinterceptor.Fail(c, err)
		} else {
			apiinterceptor.Succeed(c, http.StatusOK, resp)
		}
	}
}

// GetUpgradeOperation
// @Summary Get upgrade operation details
// @Description Retrieves the details of a specific cluster upgrade operation
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param id path string true "upgrade operation ID"
// @Success 200 {object} message.Result{data=message.GetClusterUpgradeResp}
// @Failure 404 {object} message.Result
// @Failure 500 {object} message.Result
// @Router /upgradeOperations/{id} [get]
func GetUpgradeOperation(c *gin.Context) {
	req := &message.GetClusterUpgradeReq{
		ID: c.Param("id"),
	}

	if ok := apiinterceptor.HandleJsonRequestFromQuery(c, req); ok {
		resp, err := opsservice.GetUpgradeOpService().GetUpgrade(c, *req)
		if err != nil {
			apiinterceptor.Fail(c, err)
		} else {
			apiinterceptor.Succeed(c, http.StatusOK, resp)
		}
	}
}

// PauseUpgradeOperation
// @Summary Pause an upgrade operation
// @Description Pauses a running cluster upgrade operation
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param id path string true "upgrade operation ID"
// @Success 200 {object} message.Result{data=message.PauseClusterUpgradeResp}
// @Failure 404 {object} message.Result
// @Failure 400 {object} message.Result
// @Failure 500 {object} message.Result
// @Router /upgradeOperations/{id}/pause [put]
func PauseUpgradeOperation(c *gin.Context) {
	req := &message.PauseClusterUpgradeReq{
		ID: c.Param("id"),
	}

	resp, err := opsservice.GetUpgradeOpService().PauseUpgrade(c, *req)
	if err != nil {
		apiinterceptor.Fail(c, err)
	} else {
		apiinterceptor.Succeed(c, http.StatusOK, resp)
	}
}

// ResumeUpgradeOperation
// @Summary Resume a paused upgrade operation
// @Description Resumes a paused cluster upgrade operation
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param id path string true "upgrade operation ID"
// @Success 200 {object} message.Result{data=message.ResumeClusterUpgradeResp}
// @Failure 404 {object} message.Result
// @Failure 400 {object} message.Result
// @Failure 500 {object} message.Result
// @Router /upgradeOperations/{id}/resume [put]
func ResumeUpgradeOperation(c *gin.Context) {
	req := &message.ResumeClusterUpgradeReq{
		ID: c.Param("id"),
	}

	resp, err := opsservice.GetUpgradeOpService().ResumeUpgrade(c, *req)
	if err != nil {
		apiinterceptor.Fail(c, err)
	} else {
		apiinterceptor.Succeed(c, http.StatusOK, resp)
	}
}

// DeleteUpgradeOperation
// @Summary Delete an upgrade operation
// @Description Deletes/cancels a cluster upgrade operation
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param id path string true "upgrade operation ID"
// @Success 202 {object} message.Result{data=message.DeleteClusterUpgradeResp}
// @Failure 404 {object} message.Result
// @Failure 500 {object} message.Result
// @Router /upgradeOperations/{id} [delete]
func DeleteUpgradeOperation(c *gin.Context) {
	req := &message.DeleteClusterUpgradeReq{
		ID: c.Param("id"),
	}

	resp, err := opsservice.GetUpgradeOpService().DeleteUpgrade(c, *req)
	if err != nil {
		apiinterceptor.Fail(c, err)
	} else {
		apiinterceptor.Succeed(c, http.StatusAccepted, resp)
	}
}

// DryRunUpgradeOperation
// @Summary Dry-run an upgrade operation
// @Description Dry-runs a cluster upgrade request and returns the ClusterUpgradeOperation CR that would be created without actually creating it
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param request body message.CreateClusterUpgradeReq true "create cluster upgrade request"
// @Success 200 {object} message.Result{data=message.DryRunClusterUpgradeResp}
// @Failure 400 {object} message.Result
// @Failure 500 {object} message.Result
// @Router /upgradeOperations/dry-run [post]
func DryRunUpgradeOperation(c *gin.Context) {
	req := &message.CreateClusterUpgradeReq{}
	if ok := apiinterceptor.HandleJsonRequestFromBody(c, req); ok {
		resp, err := opsservice.GetUpgradeOpService().DryRunUpgrade(c, *req)
		if err != nil {
			apiinterceptor.Fail(c, err)
		} else {
			apiinterceptor.Succeed(c, http.StatusOK, resp)
		}
	}
}

// GetNodeGroups
// @Summary Get all node groups and their versions
// @Description Lists all node groups for a cluster with their Kubernetes versions
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param k8sClusterName query string true "Kubernetes cluster name"
// @Param region query string true "Cloud region"
// @Param cloudProvider query string true "Cloud provider (eks, gke, aks, ack, mock)"
// @Success 200 {object} message.Result{data=message.GetNodeGroupsResp}
// @Failure 400 {object} message.Result
// @Failure 500 {object} message.Result
// @Router /nodeGroups [get]
func GetNodeGroups(c *gin.Context) {
	req := &message.GetNodeGroupsReq{}
	if ok := apiinterceptor.HandleJsonRequestFromQuery(c, req); ok {
		resp, err := opsservice.GetUpgradeOpService().GetNodeGroups(c, *req)
		if err != nil {
			apiinterceptor.Fail(c, err)
		} else {
			apiinterceptor.Succeed(c, http.StatusOK, resp)
		}
	}
}

// ListAddons
// @Summary List cluster addons
// @Description Lists all addons installed in the cluster with their versions and status
// @Tags upgrade-operation
// @Accept json
// @Produce json
// @Param k8sClusterName query string true "Kubernetes cluster name"
// @Param region query string true "Cloud region"
// @Param cloudProvider query string true "Cloud provider (eks, gke, aks, ack, mock)"
// @Success 200 {object} message.Result{data=message.ListAddonsResp}
// @Failure 400 {object} message.Result
// @Failure 500 {object} message.Result
// @Router /addons [get]
func ListAddons(c *gin.Context) {
	req := &message.ListAddonsReq{}
	if ok := apiinterceptor.HandleJsonRequestFromQuery(c, req); ok {
		resp, err := opsservice.GetUpgradeOpService().ListAddons(c, *req)
		if err != nil {
			apiinterceptor.Fail(c, err)
		} else {
			apiinterceptor.Succeed(c, http.StatusOK, resp)
		}
	}
}
