package domain

import (
	"time"
	"unicode/utf8"
)

// ExampleID is a strongly-typed identifier for examples.
type ExampleID string

// String returns the string representation of the ID.
func (id ExampleID) String() string {
	return string(id)
}

// IsZero returns true if the ID is empty.
func (id ExampleID) IsZero() bool {
	return id == ""
}

// Example name constraints.
const (
	MinExampleNameLen = 1
	MaxExampleNameLen = 100
	MaxDescriptionLen = 500
)

// Example represents an example domain entity.
// This is a pure domain model with no external dependencies.
type Example struct {
	ID          ExampleID
	Name        string
	Description string
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

// NewExample creates a new Example with validation.
// Returns ErrInvalidExampleName if the name is invalid.
func NewExample(id ExampleID, name, description string) (*Example, error) {
	if err := validateExampleName(name); err != nil {
		return nil, err
	}
	if err := validateDescription(description); err != nil {
		return nil, err
	}

	now := time.Now().UTC()
	return &Example{
		ID:          id,
		Name:        name,
		Description: description,
		CreatedAt:   now,
		UpdatedAt:   now,
	}, nil
}

// Update modifies the example's mutable fields with validation.
// Returns ErrInvalidExampleName if the name is invalid.
func (e *Example) Update(name, description string) error {
	if err := validateExampleName(name); err != nil {
		return err
	}
	if err := validateDescription(description); err != nil {
		return err
	}

	e.Name = name
	e.Description = description
	e.UpdatedAt = time.Now().UTC()
	return nil
}

// validateExampleName validates an example name.
func validateExampleName(name string) error {
	length := utf8.RuneCountInString(name)
	if length < MinExampleNameLen || length > MaxExampleNameLen {
		return ErrInvalidExampleName
	}
	return nil
}

// validateDescription validates a description.
func validateDescription(desc string) error {
	if utf8.RuneCountInString(desc) > MaxDescriptionLen {
		return ErrInvalidExampleName
	}
	return nil
}
