package repository

import (
	"context"
	"sync"

	"route256/loms/internal/domain/entity"
	"route256/loms/internal/domain/model"
)

type storage = map[entity.ID]*entity.Order

type InMemoryRepository struct {
	storage   storage
	mx        sync.RWMutex
	idCounter entity.ID
}

func NewInMemoryRepository(cap int) *InMemoryRepository {
	return &InMemoryRepository{
		storage: make(storage, cap),
	}
}

func (r *InMemoryRepository) OrderCreate(_ context.Context, order *entity.Order) (entity.ID, error) {
	r.mx.Lock()
	defer r.mx.Unlock()

	r.idCounter++

	orderCopy := &entity.Order{
		OrderID: r.idCounter,
		Status:  order.Status,
		UserID:  order.UserID,
		Items:   make([]entity.OrderItem, len(order.Items)),
	}

	copy(orderCopy.Items, order.Items)

	r.storage[orderCopy.OrderID] = orderCopy

	return r.idCounter, nil
}

func (r *InMemoryRepository) OrderSetStatus(_ context.Context, orderID entity.ID, newStatus string) error {
	r.mx.Lock()
	defer r.mx.Unlock()

	if _, ok := r.storage[orderID]; !ok {
		return model.ErrOrderNotFound
	}

	r.storage[orderID].Status = newStatus

	return nil
}

func (r *InMemoryRepository) OrderGetByID(_ context.Context, orderID entity.ID) (*entity.Order, error) {
	r.mx.Lock()
	defer r.mx.Unlock()

	order, ok := r.storage[orderID]
	if !ok {
		return nil, model.ErrOrderNotFound
	}

	orderCopy := &entity.Order{
		OrderID: order.OrderID,
		Status:  order.Status,
		UserID:  order.UserID,
		Items:   make([]entity.OrderItem, len(order.Items)),
	}

	copy(orderCopy.Items, order.Items)

	return orderCopy, nil
}
