package vpcpeering

import (
	"net/http"

	"github.com/gin-gonic/gin"

	regionalapiv1 "github.com/tidbcloud/infra-provider/api/tidbcloud/regional-server/v1"
	bizerr "github.com/tidbcloud/infra-provider/regional-server/pkg/common/errors"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/common/message"
	_ "github.com/tidbcloud/infra-provider/regional-server/pkg/resourcemanager/vpcpeering"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/router/interceptor"
	servpcpeering "github.com/tidbcloud/infra-provider/regional-server/pkg/service/vpcpeering"
)

type VPCPeeringHandler struct {
	svc *servpcpeering.Service
}

func NewVPCPeeringHandler(svc *servpcpeering.Service) *VPCPeeringHandler {
	return &VPCPeeringHandler{
		svc: svc,
	}
}

func (handler *VPCPeeringHandler) CreateVPCPeering(c *gin.Context) {
	req := &regionalapiv1.CreateVpcPeeringRequest{
		VpcPeering: new(regionalapiv1.VpcPeering),
	}
	if ok := interceptor.HandleJsonPbRequestFromBody(c, req.VpcPeering); !ok {
		return
	}
	if err := (&message.CreateVpcPeeringReqValidatable{CreateVpcPeeringRequest: req}).Validate(); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
		return
	}
	switch handler.svc.GetProvider() {
	case "aws":
		if info := req.VpcPeering.GetAws(); info == nil {
			interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, "vpcPeering.aws is nil"))
			return
		} else if err := (&message.AWSInfoValidatable{VpcPeering_Aws: info}).Validate(); err != nil {
			interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
			return
		}
	case "gcp":
		if info := req.VpcPeering.GetGcp(); info == nil {
			interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, "vpcPeering.gcp is nil"))
			return
		} else if err := (&message.GCPInfoValidatable{VpcPeering_Gcp: info}).Validate(); err != nil {
			interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
			return
		}
	default:
		interceptor.Fail(c, bizerr.New(bizerr.ConfigInvalid, "provider config invalid"))
		return
	}
	resp, err := handler.svc.Create(c, req)
	if err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.SucceedPb(c, http.StatusAccepted, resp)
}

func (handler *VPCPeeringHandler) DeleteVPCPeering(c *gin.Context) {
	req := new(regionalapiv1.DeleteVpcPeeringRequest)
	req.VpcPeeringId = c.Param("vpcPeeringId")
	if err := (&message.DeleteVpcPeeringReqValidatable{DeleteVpcPeeringRequest: req}).Validate(); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
		return
	}
	resp, err := handler.svc.Delete(c, req)
	if err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.SucceedPb(c, http.StatusOK, resp)
}

func (handler *VPCPeeringHandler) GetVPCPeering(c *gin.Context) {
	req := new(regionalapiv1.GetVpcPeeringRequest)
	req.VpcPeeringId = c.Param("vpcPeeringId")
	req.ShowStatusOnly = c.Query("showStatusOnly") == "true"
	if err := (&message.GetVpcPeeringReqValidatable{GetVpcPeeringRequest: req}).Validate(); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
		return
	}
	resp, err := handler.svc.Get(c, req)
	if err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.SucceedPb(c, http.StatusOK, resp)
}

func (handler *VPCPeeringHandler) ListVPCPeering(c *gin.Context) {
	req := new(regionalapiv1.ListVpcPeeringsRequest)
	req.TenantId = c.Query("tenantId")
	req.ProjectId = c.Query("projectId")
	req.ShowStatusOnly = c.Query("showStatusOnly") == "true"
	if err := (&message.ListVpcPeeringReqValidatable{ListVpcPeeringsRequest: req}).Validate(); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
		return
	}
	resp, err := handler.svc.List(c, req)
	if err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.SucceedPb(c, http.StatusOK, resp)
}

func (handler *VPCPeeringHandler) AcceptVPCPeering(c *gin.Context) {
	req := &regionalapiv1.AcceptVpcPeeringRequest{}
	if ok := interceptor.HandleJsonPbRequestFromBody(c, req); !ok {
		return
	}
	if err := (&message.AcceptVpcPeeringReqValidatable{AcceptVpcPeeringRequest: req}).Validate(); err != nil {
		interceptor.Fail(c, bizerr.New(bizerr.ParameterInvalid, err.Error()))
		return
	}
	resp, err := handler.svc.Accept(c, req)
	if err != nil {
		interceptor.Fail(c, err)
		return
	}
	interceptor.SucceedPb(c, http.StatusAccepted, resp)
}
