package validator

import (
	"apskel-pos-be/internal/constants"
	"apskel-pos-be/internal/contract"
	"errors"
	"strings"
)

type IngredientUnitConverterValidator interface {
	ValidateCreateIngredientUnitConverterRequest(req *contract.CreateIngredientUnitConverterRequest) (error, string)
	ValidateUpdateIngredientUnitConverterRequest(req *contract.UpdateIngredientUnitConverterRequest) (error, string)
	ValidateListIngredientUnitConvertersRequest(req *contract.ListIngredientUnitConvertersRequest) (error, string)
	ValidateConvertUnitRequest(req *contract.ConvertUnitRequest) (error, string)
}

type IngredientUnitConverterValidatorImpl struct{}

func NewIngredientUnitConverterValidator() IngredientUnitConverterValidator {
	return &IngredientUnitConverterValidatorImpl{}
}

func (v *IngredientUnitConverterValidatorImpl) ValidateCreateIngredientUnitConverterRequest(req *contract.CreateIngredientUnitConverterRequest) (error, string) {
	if req == nil {
		return errors.New("request cannot be nil"), constants.ValidationErrorCode
	}

	// Validate required fields
	if req.IngredientID.String() == "" {
		return errors.New("ingredient_id is required"), constants.MissingFieldErrorCode
	}

	if req.FromUnitID.String() == "" {
		return errors.New("from_unit_id is required"), constants.MissingFieldErrorCode
	}

	if req.ToUnitID.String() == "" {
		return errors.New("to_unit_id is required"), constants.MissingFieldErrorCode
	}

	if req.ConversionFactor <= 0 {
		return errors.New("conversion_factor must be greater than 0"), constants.ValidationErrorCode
	}

	// Validate that from and to units are different
	if req.FromUnitID == req.ToUnitID {
		return errors.New("from_unit_id and to_unit_id must be different"), constants.ValidationErrorCode
	}

	return nil, ""
}

func (v *IngredientUnitConverterValidatorImpl) ValidateUpdateIngredientUnitConverterRequest(req *contract.UpdateIngredientUnitConverterRequest) (error, string) {
	if req == nil {
		return errors.New("request cannot be nil"), constants.ValidationErrorCode
	}

	// At least one field must be provided for update
	if req.FromUnitID == nil && req.ToUnitID == nil && req.ConversionFactor == nil && req.IsActive == nil {
		return errors.New("at least one field must be provided for update"), constants.ValidationErrorCode
	}

	// Validate conversion factor if provided
	if req.ConversionFactor != nil && *req.ConversionFactor <= 0 {
		return errors.New("conversion_factor must be greater than 0"), constants.ValidationErrorCode
	}

	// Validate that from and to units are different if both are provided
	if req.FromUnitID != nil && req.ToUnitID != nil && *req.FromUnitID == *req.ToUnitID {
		return errors.New("from_unit_id and to_unit_id must be different"), constants.ValidationErrorCode
	}

	return nil, ""
}

func (v *IngredientUnitConverterValidatorImpl) ValidateListIngredientUnitConvertersRequest(req *contract.ListIngredientUnitConvertersRequest) (error, string) {
	if req == nil {
		return errors.New("request cannot be nil"), constants.ValidationErrorCode
	}

	// Validate pagination
	if req.Page < 1 {
		return errors.New("page must be at least 1"), constants.ValidationErrorCode
	}

	if req.Limit < 1 || req.Limit > 100 {
		return errors.New("limit must be between 1 and 100"), constants.ValidationErrorCode
	}

	// Validate search string length
	if req.Search != "" && len(strings.TrimSpace(req.Search)) < 2 {
		return errors.New("search term must be at least 2 characters"), constants.ValidationErrorCode
	}

	return nil, ""
}

func (v *IngredientUnitConverterValidatorImpl) ValidateConvertUnitRequest(req *contract.ConvertUnitRequest) (error, string) {
	if req == nil {
		return errors.New("request cannot be nil"), constants.ValidationErrorCode
	}

	// Validate required fields
	if req.IngredientID.String() == "" {
		return errors.New("ingredient_id is required"), constants.MissingFieldErrorCode
	}

	if req.FromUnitID.String() == "" {
		return errors.New("from_unit_id is required"), constants.MissingFieldErrorCode
	}

	if req.ToUnitID.String() == "" {
		return errors.New("to_unit_id is required"), constants.MissingFieldErrorCode
	}

	if req.Quantity <= 0 {
		return errors.New("quantity must be greater than 0"), constants.ValidationErrorCode
	}

	return nil, ""
}

