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 iAddress interface {
	CreateAddress(ctx *gin.Context)
	UpdateAddress(ctx *gin.Context)
	DeleteAddress(ctx *gin.Context)
	GetAddress(ctx *gin.Context)
}

func (s *serviceImpl) CreateAddress(c *gin.Context) {
	req := &dto.CreateAddressRequest{}
	if err := gin2.BindData(c, &req, gin2.BindType_JSON); err != nil {
		gin2.ResponseBadRequest(c, err)
		return
	}

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

	res, err := s.addressDomain.CreateAddress(getCtx(c), transform.CreateAddressRequestDTOToEntity(req, country.CountryId))
	if err != nil {
		gin2.ResponseInternalServerError(c, err)
		return
	}
	gin2.ResponseSuccess(c, transform.AddressEntityToDTO(res))
}

func (s *serviceImpl) UpdateAddress(c *gin.Context) {
	req := &dto.UpdateAddressRequest{}
	if err := gin2.BindData(c, &req, gin2.BindType_JSON, gin2.BindType_URI); err != nil {
		gin2.ResponseBadRequest(c, err)
		return
	}
	if err := s.addressDomain.UpdateAddress(getCtx(c), entities.IDFromInt64(req.ID), transform.UpdateAddressRequestDTOToEntity(req)); err != nil {
		gin2.ResponseInternalServerError(c, err)
		return
	}
	gin2.ResponseNoContent(c)
}

func (s *serviceImpl) DeleteAddress(c *gin.Context) {
	req := &dto.DeleteAddressRequest{}
	if err := gin2.BindData(c, req, gin2.BindType_URI); err != nil {
		gin2.ResponseBadRequest(c, err)
		return
	}

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

func (s *serviceImpl) GetAddress(c *gin.Context) {
	var req dto.GetAddressRequest
	if err := gin2.BindData(c, &req, gin2.BindType_URI); err != nil {
		gin2.ResponseBadRequest(c, err)
		return
	}

	ctx := getCtx(c)
	address, err := s.addressDomain.GetAddressByID(ctx, entities.IDFromInt64(req.ID))
	if err != nil {
		gin2.ResponseInternalServerError(c, err)
		return
	}

	gin2.ResponseSuccess(c, transform.AddressEntityToDTO(address))
}
