package catalog

import (
	"rmser/internal/domain/catalog"

	"github.com/google/uuid"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type pgRepository struct {
	db *gorm.DB
}

func NewRepository(db *gorm.DB) catalog.Repository {
	return &pgRepository{db: db}
}

func (r *pgRepository) SaveProducts(products []catalog.Product) error {
	// Сортировка (родители -> дети)
	sorted := sortProductsByHierarchy(products)
	return r.db.Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "id"}},
		UpdateAll: true,
	}).CreateInBatches(sorted, 100).Error
}

func (r *pgRepository) GetAll() ([]catalog.Product, error) {
	var products []catalog.Product
	err := r.db.Find(&products).Error
	return products, err
}

// Вспомогательная функция сортировки
func sortProductsByHierarchy(products []catalog.Product) []catalog.Product {
	if len(products) == 0 {
		return products
	}
	childrenMap := make(map[uuid.UUID][]catalog.Product)
	var roots []catalog.Product
	allIDs := make(map[uuid.UUID]struct{}, len(products))

	for _, p := range products {
		allIDs[p.ID] = struct{}{}
	}

	for _, p := range products {
		if p.ParentID == nil {
			roots = append(roots, p)
		} else {
			if _, exists := allIDs[*p.ParentID]; exists {
				childrenMap[*p.ParentID] = append(childrenMap[*p.ParentID], p)
			} else {
				roots = append(roots, p)
			}
		}
	}

	result := make([]catalog.Product, 0, len(products))
	queue := roots
	for len(queue) > 0 {
		current := queue[0]
		queue = queue[1:]
		result = append(result, current)
		if children, ok := childrenMap[current.ID]; ok {
			queue = append(queue, children...)
			delete(childrenMap, current.ID)
		}
	}
	for _, remaining := range childrenMap {
		result = append(result, remaining...)
	}
	return result
}

// GetActiveGoods возвращает только активные товары (не удаленные, тип GOODS)
func (r *pgRepository) GetActiveGoods() ([]catalog.Product, error) {
	var products []catalog.Product
	// iikoRMS: GOODS - товары, PREPARED - заготовки (иногда их тоже покупают)
	err := r.db.Where("is_deleted = ? AND type IN ?", false, []string{"GOODS"}).
		Order("name ASC").
		Find(&products).Error
	return products, err
}
