// Package memory provides in-memory implementations of repository interfaces.
// Useful for development, testing, and prototyping.
package memory

import (
	"context"
	"sync"

	"{{GO_MODULE}}/services/{{COMPONENT_NAME}}/internal/domain"
	"{{GO_MODULE}}/services/{{COMPONENT_NAME}}/internal/port"
)

// Compile-time verification that ExampleRepository implements port.ExampleRepository.
var _ port.ExampleRepository = (*ExampleRepository)(nil)

// ExampleRepository is a thread-safe in-memory implementation of port.ExampleRepository.
type ExampleRepository struct {
	mu       sync.RWMutex
	examples map[domain.ExampleID]*domain.Example
}

// NewExampleRepository creates a new in-memory example repository.
func NewExampleRepository() *ExampleRepository {
	return &ExampleRepository{
		examples: make(map[domain.ExampleID]*domain.Example),
	}
}

// List returns all examples.
func (r *ExampleRepository) List(ctx context.Context) ([]domain.Example, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	result := make([]domain.Example, 0, len(r.examples))
	for _, e := range r.examples {
		result = append(result, *e)
	}
	return result, nil
}

// Get returns an example by ID.
// Returns domain.ErrExampleNotFound if not found.
func (r *ExampleRepository) Get(ctx context.Context, id domain.ExampleID) (*domain.Example, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	e, ok := r.examples[id]
	if !ok {
		return nil, domain.ErrExampleNotFound
	}
	// Return a copy to prevent external mutation
	copy := *e
	return &copy, nil
}

// Create stores a new example.
func (r *ExampleRepository) Create(ctx context.Context, example *domain.Example) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	// Store a copy to prevent external mutation
	copy := *example
	r.examples[example.ID] = &copy
	return nil
}

// Update modifies an existing example.
// Returns domain.ErrExampleNotFound if not found.
func (r *ExampleRepository) Update(ctx context.Context, example *domain.Example) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	if _, ok := r.examples[example.ID]; !ok {
		return domain.ErrExampleNotFound
	}
	// Store a copy to prevent external mutation
	copy := *example
	r.examples[example.ID] = &copy
	return nil
}

// Delete removes an example by ID.
// Returns domain.ErrExampleNotFound if not found.
func (r *ExampleRepository) Delete(ctx context.Context, id domain.ExampleID) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	if _, ok := r.examples[id]; !ok {
		return domain.ErrExampleNotFound
	}
	delete(r.examples, id)
	return nil
}

// ExistsByName checks if an example with the given name exists.
func (r *ExampleRepository) ExistsByName(ctx context.Context, name string) (bool, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	for _, e := range r.examples {
		if e.Name == name {
			return true, nil
		}
	}
	return false, nil
}
