package validator

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

	"github.com/go-playground/validator/v10"
)

type CustomerValidator interface {
	ValidateCreateCustomerRequest(req *contract.CreateCustomerRequest) (error, string)
	ValidateUpdateCustomerRequest(req *contract.UpdateCustomerRequest) (error, string)
	ValidateListCustomersRequest(req *contract.ListCustomersRequest) (error, string)
	ValidateSetDefaultCustomerRequest(req *contract.SetDefaultCustomerRequest) (error, string)
}

type CustomerValidatorImpl struct {
	validate *validator.Validate
}

func NewCustomerValidator() *CustomerValidatorImpl {
	return &CustomerValidatorImpl{
		validate: validator.New(),
	}
}

// ValidateCreateCustomer validates create customer request
func (v *CustomerValidatorImpl) ValidateCreateCustomerRequest(req *contract.CreateCustomerRequest) (error, string) {
	if err := v.validate.Struct(req); err != nil {
		return err, "VALIDATION_ERROR"
	}

	// Additional custom validations
	if req.Name != "" {
		req.Name = strings.TrimSpace(req.Name)
		if req.Name == "" {
			return errors.New("name cannot be empty or whitespace only"), "INVALID_NAME"
		}
		if len(req.Name) > 255 {
			return errors.New("name cannot exceed 255 characters"), "INVALID_NAME"
		}
	}

	if req.Email != nil && *req.Email != "" {
		*req.Email = strings.TrimSpace(strings.ToLower(*req.Email))
		if *req.Email == "" {
			return errors.New("email cannot be empty or whitespace only"), "INVALID_EMAIL"
		}
		if len(*req.Email) > 255 {
			return errors.New("email cannot exceed 255 characters"), "INVALID_EMAIL"
		}
	}

	if req.Phone != nil && *req.Phone != "" {
		*req.Phone = strings.TrimSpace(*req.Phone)
		if *req.Phone == "" {
			return errors.New("phone cannot be empty or whitespace only"), "INVALID_PHONE"
		}
		if len(*req.Phone) > 20 {
			return errors.New("phone cannot exceed 20 characters"), "INVALID_PHONE"
		}
	}

	if req.Address != nil && *req.Address != "" {
		*req.Address = strings.TrimSpace(*req.Address)
		if *req.Address == "" {
			return errors.New("address cannot be empty or whitespace only"), "INVALID_ADDRESS"
		}
		if len(*req.Address) > 500 {
			return errors.New("address cannot exceed 500 characters"), "INVALID_ADDRESS"
		}
	}

	return nil, ""
}

// ValidateUpdateCustomer validates update customer request
func (v *CustomerValidatorImpl) ValidateUpdateCustomerRequest(req *contract.UpdateCustomerRequest) (error, string) {
	if err := v.validate.Struct(req); err != nil {
		return err, "VALIDATION_ERROR"
	}

	// Check if at least one field is provided
	if req.Name == nil && req.Email == nil && req.Phone == nil && req.Address == nil && req.IsActive == nil {
		return errors.New("at least one field must be provided for update"), "MISSING_FIELDS"
	}

	// Additional custom validations
	if req.Name != nil && *req.Name != "" {
		*req.Name = strings.TrimSpace(*req.Name)
		if *req.Name == "" {
			return errors.New("name cannot be empty or whitespace only"), "INVALID_NAME"
		}
		if len(*req.Name) > 255 {
			return errors.New("name cannot exceed 255 characters"), "INVALID_NAME"
		}
	}

	if req.Email != nil && *req.Email != "" {
		*req.Email = strings.TrimSpace(strings.ToLower(*req.Email))
		if *req.Email == "" {
			return errors.New("email cannot be empty or whitespace only"), "INVALID_EMAIL"
		}
		if len(*req.Email) > 255 {
			return errors.New("email cannot exceed 255 characters"), "INVALID_EMAIL"
		}
	}

	if req.Phone != nil && *req.Phone != "" {
		*req.Phone = strings.TrimSpace(*req.Phone)
		if *req.Phone == "" {
			return errors.New("phone cannot be empty or whitespace only"), "INVALID_PHONE"
		}
		if len(*req.Phone) > 20 {
			return errors.New("phone cannot exceed 20 characters"), "INVALID_PHONE"
		}
	}

	if req.Address != nil && *req.Address != "" {
		*req.Address = strings.TrimSpace(*req.Address)
		if *req.Address == "" {
			return errors.New("address cannot be empty or whitespace only"), "INVALID_ADDRESS"
		}
		if len(*req.Address) > 500 {
			return errors.New("address cannot exceed 500 characters"), "INVALID_ADDRESS"
		}
	}

	return nil, ""
}

// ValidateListCustomersRequest validates list customers request
func (v *CustomerValidatorImpl) ValidateListCustomersRequest(req *contract.ListCustomersRequest) (error, string) {
	if err := v.validate.Struct(req); err != nil {
		return err, "VALIDATION_ERROR"
	}

	// Additional custom validations
	if req.Search != "" {
		req.Search = strings.TrimSpace(req.Search)
		if len(req.Search) > 100 {
			return errors.New("search term cannot exceed 100 characters"), "INVALID_SEARCH"
		}
	}

	if req.SortBy != "" {
		req.SortBy = strings.ToLower(strings.TrimSpace(req.SortBy))
		validSortFields := map[string]bool{
			"name":       true,
			"email":      true,
			"created_at": true,
			"updated_at": true,
		}
		if !validSortFields[req.SortBy] {
			return errors.New("invalid sort field"), "INVALID_SORT_FIELD"
		}
	}

	if req.SortOrder != "" {
		req.SortOrder = strings.ToLower(strings.TrimSpace(req.SortOrder))
		if req.SortOrder != "asc" && req.SortOrder != "desc" {
			return errors.New("sort order must be 'asc' or 'desc'"), "INVALID_SORT_ORDER"
		}
	}

	return nil, ""
}

// ValidateSetDefaultCustomer validates set default customer request
func (v *CustomerValidatorImpl) ValidateSetDefaultCustomerRequest(req *contract.SetDefaultCustomerRequest) (error, string) {
	if err := v.validate.Struct(req); err != nil {
		return err, "VALIDATION_ERROR"
	}
	return nil, ""
}
