package adminkindboxreqvalidator

import (
	"context"
	"errors"
	"fmt"

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

const (
	MinKindBoxReq = 1
	MaxKindBoxReq = 100
)

type Repository interface {
	KindBoxRequestExist(id uint) (bool, error)
	GetByID(ctx context.Context, id uint) (entity.KindBoxReq, error)
}

type AdminSvc interface {
	AdminExistByID(ctx context.Context, req param.AdminExistByIDRequest) (param.AdminExistByIDResponse, error)
}

type Validator struct {
	repo     Repository
	adminSvc AdminSvc
}

func New(repo Repository, adminSvc AdminSvc) Validator {
	return Validator{repo: repo, adminSvc: adminSvc}
}

func (v Validator) doesKindBoxRequestExist(value interface{}) error {
	kindboxreqID, ok := value.(uint)
	if !ok {
		return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
	}
	if isExist, err := v.repo.KindBoxRequestExist(kindboxreqID); !isExist || err != nil {
		if err != nil {
			return err
		}
		if !isExist {
			return errors.New("kind box request is not exist")
		}
	}

	return nil
}

func (v Validator) CheckKindBoxReqStatusForAccepting(value interface{}) error {
	kindboxreqID, ok := value.(uint)
	if !ok {
		return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
	}
	kindBox, err := v.repo.GetByID(context.Background(), kindboxreqID)
	if err != nil {
		return err
	}
	if kindBox.Status != entity.KindBoxReqPendingStatus {
		return fmt.Errorf(errmsg.ErrorMsgAcceptKindBoxReqStatus)
	}

	return nil
}

func (v Validator) CheckKindBoxReqStatusForRejecting(value interface{}) error {
	kindboxreqID, ok := value.(uint)
	if !ok {
		return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
	}
	kindBox, err := v.repo.GetByID(context.Background(), kindboxreqID)
	if err != nil {
		return err
	}
	if kindBox.Status != entity.KindBoxReqPendingStatus {
		return fmt.Errorf(errmsg.ErrorMsgRejectKindBoxReqStatus)
	}

	return nil
}
func (v Validator) checkKindBoxReqStatusForDelivering(value interface{}) error {
	kindboxreqID, ok := value.(uint)
	if !ok {
		return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
	}
	kindBoxReq, err := v.repo.GetByID(context.Background(), kindboxreqID)
	if err != nil {
		return err
	}
	if kindBoxReq.Status != entity.KindBoxReqAssignedSenderAgentStatus {
		return fmt.Errorf(errmsg.ErrorMsgDeliverKindBoxReqStatus)
	}

	return nil
}
func (v Validator) checkKindBoxReqStatusForAssigningSenderAgent(value interface{}) error {
	kindboxreqID, ok := value.(uint)
	if !ok {
		return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
	}
	kindBoxReq, err := v.repo.GetByID(context.Background(), kindboxreqID)
	if err != nil {
		return err
	}
	if kindBoxReq.Status != entity.KindBoxReqAcceptedStatus {
		return fmt.Errorf(errmsg.ErrorMsgAssignSenderAgentKindBoxReqStatus)
	}

	return nil
}

func (v Validator) checkCountAcceptedMustBeLessThanCountRequested(kindboxreqID uint) validation.RuleFunc {
	return func(value interface{}) error {
		countAccepted, ok := value.(uint)
		if !ok {
			return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
		}
		kindBoxReq, err := v.repo.GetByID(context.Background(), kindboxreqID)
		if err != nil {
			return err
		}
		if kindBoxReq.CountRequested < countAccepted {
			return fmt.Errorf(errmsg.ErrorMsgCountAcceptedOverflow)
		}
		return nil
	}
}

func (v Validator) doesAgentAdminExist(value interface{}) error {
	adminID, ok := value.(uint)
	if !ok {
		return fmt.Errorf(errmsg.ErrorMsgSomethingWentWrong)
	}
	resp, err := v.adminSvc.AdminExistByID(context.Background(), param.AdminExistByIDRequest{
		AdminID: adminID,
	})
	if err != nil {
		return err
	}
	if resp.Admin.Role != entity.AdminAgentRole {
		return fmt.Errorf(errmsg.ErrorMsgAdminIsNotAgent)
	}

	return nil
}
