package adminkindboxvalidator

import (
	"context"

	entity "git.gocasts.ir/ebhomengo/niki/entity"
	param "git.gocasts.ir/ebhomengo/niki/param/admin/kind_box"
	errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
	richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
	validation "github.com/go-ozzo/ozzo-validation/v4"
)

func (v Validator) ValidateUpdateRequest(ctx context.Context, req param.KindBoxUpdateRequest) (map[string]string, error) {
	const op = "adminkindboxvalidator.ValidateUpdateRequest"

	err := validation.ValidateStruct(&req,
		validation.Field(&req.KindBoxID,
			validation.Required,
			validation.By(v.doesKindBoxExist(ctx))),
		validation.Field(&req.BenefactorID,
			validation.Required,
			validation.By(v.doesBenefactorExist(ctx)),
			validation.By(v.doesBenefactorHaveKindBox(ctx, req.KindBoxID, req.BenefactorID))),
	)
	if err != nil {
		fieldErrors := make(map[string]string)
		v.processValidationErrors(err, fieldErrors)
		return fieldErrors, richerror.New(op).
			WithMessage(errmsg.ErrorMsgInvalidInput).
			WithKind(richerror.KindInvalid).
			WithMeta(map[string]interface{}{"req": req}).
			WithErr(err)
	}

	kindBox, err := v.repo.GetKindBox(ctx, req.KindBoxID)
	if err != nil {
		return nil, richerror.New(op).
			WithMessage(errmsg.ErrorMsgSomethingWentWrong).
			WithKind(richerror.KindUnexpected).
			WithMeta(map[string]interface{}{"req": req}).
			WithErr(err)
	}

	var sErr error
	fieldErrors := make(map[string]string)

	switch kindBox.Status {
	case entity.KindBoxDeliveredStatus, entity.KindBoxReturnedStatus:
		fieldErrors["KindBoxID"] = errmsg.ErrorMsgCantUpdateRecord

	case entity.KindBoxReadyToReturnStatus:
		if req.Amount != 0 {
			fieldErrors["Amount"] = errmsg.ErrorMsgInvalidInput
		}
		if req.ReceiverAgentID != 0 {
			fieldErrors["Receiver Agent Id"] = errmsg.ErrorMsgInvalidInput
		} else {
			sErr = validation.ValidateStruct(&req,
				validation.Field(&req.ReturnAddressID,
					validation.Required,
					validation.By(v.doesBenefactorAddressExist(ctx, req.KindBoxID, req.BenefactorID, req.ReturnAddressID)),
				),
				validation.Field(&req.ReturnReferDate,
					validation.Required,
					validation.By(v.isDateValid),
				),
				validation.Field(&req.ReturnReferTimeID,
					validation.Required,
					validation.By(v.isReturnReferTimeIDValid(ctx)),
				),
			)
		}

	case entity.KindBoxAssignedReceiverAgentStatus:
		if req.Amount != 0 {
			fieldErrors["Amount"] = errmsg.ErrorMsgInvalidInput
		}
		if req.ReturnReferTimeID != 0 {
			fieldErrors["Return Refer Time Id"] = errmsg.ErrorMsgInvalidInput
		}
		if !req.ReturnReferDate.IsZero() {
			fieldErrors["Return Refer Date"] = errmsg.ErrorMsgInvalidInput
		}
		if req.ReturnAddressID != 0 {
			fieldErrors["Return Address ID"] = errmsg.ErrorMsgInvalidInput
		} else {
			sErr = validation.ValidateStruct(&req,
				validation.Field(&req.ReceiverAgentID, validation.Required,
					validation.By(v.doesAgentExist(ctx))),
			)
		}

	case entity.KindBoxEnumeratedStatus:
		if req.ReceiverAgentID != 0 {
			fieldErrors["Receiver Agent ID"] = errmsg.ErrorMsgInvalidInput
		}
		if req.ReturnReferTimeID != 0 {
			fieldErrors["Return Refer Time Id"] = errmsg.ErrorMsgInvalidInput
		}
		if !req.ReturnReferDate.IsZero() {
			fieldErrors["Return Refer Date"] = errmsg.ErrorMsgInvalidInput
		}
		if req.ReturnAddressID != 0 {
			fieldErrors["Return Address ID"] = errmsg.ErrorMsgInvalidInput
		} else {
			sErr = validation.ValidateStruct(&req,
				validation.Field(&req.Amount, validation.Required,
					validation.By(v.isAmountValid(ctx))),
			)
		}
	}

	if sErr != nil {
		v.processValidationErrors(sErr, fieldErrors)
		return fieldErrors, richerror.New(op).
			WithMessage(errmsg.ErrorMsgInvalidInput).
			WithKind(richerror.KindInvalid).
			WithMeta(map[string]interface{}{"req": req}).
			WithErr(sErr)
	}

	if len(fieldErrors) > 0 {
		return fieldErrors, richerror.New(op).
			WithMessage(errmsg.ErrorMsgInvalidInput).
			WithKind(richerror.KindInvalid).
			WithMeta(map[string]interface{}{"req": req})
	}

	return nil, nil
}
