package service

import (
	"net/http"

	gin2 "github.com/UpmeshLTD/urus-aio/infrastructure/server/transport/http/gin"
	mdmpb "github.com/UpmeshLTD/urus-aio/shipment/external/mdm/pb"

	"github.com/UpmeshLTD/urus-aio/infrastructure/db/entities"
	"github.com/UpmeshLTD/urus-aio/shipment/server/http/dto"
	"github.com/UpmeshLTD/urus-aio/shipment/service/transform"
	"github.com/gin-gonic/gin"
)

type iDeliveryPlan interface {
	GetDeliveryPlans(c *gin.Context)
	CreateDeliveryPlan(c *gin.Context)
	UpdateDeliveryPlan(c *gin.Context)
	DeleteDeliveryPlan(c *gin.Context)
}

// GetDeliveryPlans godoc
// @Summary Get list of all delivery plans.
// @Description Get list of all delivery plans.
// @Tags Delivery Plan
// @Accept */*
// @Produce json
// @Param GetDeliveryPlansRequest query dto.GetDeliveryPlansRequest false "GetDeliveryPlansRequest"
// @Success 200 {object} dto.GetDeliveryPlansResponse
// @Security BearerToken
// @Router /delivery-plans [GET]
func (s *serviceImpl) GetDeliveryPlans(c *gin.Context) {
	req := &dto.GetDeliveryPlansRequest{}
	if err := gin2.BindData(c, req, gin2.BindType_Query); err != nil {
		gin2.ResponseBadRequest(c, err)
		return
	}

	country, err := s.mdmClient.GetCountryByCode(c, &mdmpb.GetCountryByCodeRequest{Code: req.CountryCode})
	if err != nil {
		gin2.ResponseErrorWithCode(c, http.StatusBadRequest, err)
		return
	}

	result, err := s.deliveryPlanDomain.GetDeliveryPlans(getCtx(c), transform.GetDeliveryPlansRequestDTOToEntity(req, country.CountryId))
	if err != nil {
		gin2.ResponseInternalServerError(c, err)
		return
	}
	gin2.ResponseSuccess(c, transform.GetDeliveryPlansResponseEntityToDTO(result))
}

// CreateDeliveryPlan godoc
// @Summary CreateDeliveryPlan
// @Description Create a new delivery plan
// @Tags Delivery Plan
// @Accept json
// @Produce json
// @Param request body dto.CreateDeliveryPlanRequest true "request"
// @Success 200 {object} dto.DeliveryPlan
// @Security BearerToken
// @Router /delivery-plans [POST]
func (s *serviceImpl) CreateDeliveryPlan(c *gin.Context) {
	req := &dto.CreateDeliveryPlanRequest{}
	if err := gin2.BindData(c, req, gin2.BindType_JSON); err != nil {
		gin2.ResponseBadRequest(c, err)
		return
	}

	res, err := s.deliveryPlanDomain.CreateDeliveryPlan(getCtx(c), transform.CreateDeliveryPlanRequestDTOToEntity(req))

	if err != nil || res == nil {
		gin2.ResponseInternalServerError(c, err)
		return
	}

	gin2.ResponseSuccess(c, transform.DeliveryPlanEntityToDTO(res))
}

// UpdateDeliveryPlan godoc
// @Summary UpdateDeliveryPlan
// @Description Update a delivery plan
// @Tags Delivery Plan
// @Accept json
// @Produce json
// @Param id path int true "DeliveryPlan ID"
// @Param request body dto.UpdateDeliveryPlanRequest true "Update DeliveryPlan"
// @Success 204
// @Security BearerToken
// @Router /delivery-plans/{id} [PUT]
func (s *serviceImpl) UpdateDeliveryPlan(c *gin.Context) {
	req := &dto.UpdateDeliveryPlanRequest{}
	if err := gin2.BindData(c, req, gin2.BindType_JSON, gin2.BindType_URI); err != nil {
		gin2.ResponseBadRequest(c, err)
		return
	}

	if err := s.deliveryPlanDomain.UpdateDeliveryPlan(getCtx(c), entities.IDFromInt64(req.ID), transform.UpdateDeliveryPlanRequestDTOToEntity(req)); err != nil {
		gin2.ResponseInternalServerError(c, err)
		return
	}
	gin2.ResponseNoContent(c)
}

// DeleteDeliveryPlan godoc
// @Summary DeleteDeliveryPlan
// @Description Delete a delivery plan
// @Tags Delivery Plan
// @Accept json
// @Produce json
// @Param id path int true "DeliveryPlan ID"
// @Success 204
// @Security BearerToken
// @Router /delivery-plans/{id} [DELETE]
func (s *serviceImpl) DeleteDeliveryPlan(c *gin.Context) {
	req := &dto.DeleteDeliveryPlanRequest{}
	if err := gin2.BindData(c, req, gin2.BindType_URI); err != nil {
		gin2.ResponseBadRequest(c, err)
		return
	}

	if err := s.deliveryPlanDomain.DeleteDeliveryPlan(getCtx(c), entities.IDFromInt64(req.ID)); err != nil {
		gin2.ResponseInternalServerError(c, err)
		return
	}
	gin2.ResponseNoContent(c)
}
