package listRepo

import (
	"git.ma-al.com/goc_daniel/b2b/app/config"
	"git.ma-al.com/goc_daniel/b2b/app/db"
	"git.ma-al.com/goc_daniel/b2b/app/model"
	"git.ma-al.com/goc_daniel/b2b/app/model/dbmodel"
	"git.ma-al.com/goc_daniel/b2b/app/utils/query/filters"
	"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
	"git.ma-al.com/goc_marek/gormcol"
	"github.com/WinterYukky/gorm-extra-clause-plugin/exclause"
)

type UIListRepo interface {
	ListProducts(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.ProductInList], error)
	ListUsers(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.UserInList], error)
}

type ListRepo struct{}

func New() UIListRepo {
	return &ListRepo{}
}

func (repo *ListRepo) ListProducts(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.ProductInList], error) {
	var list []model.ProductInList
	var total int64

	query := db.Get().
		Table(gormcol.Field.Tab(dbmodel.PsProductShopCols.Active)+" AS ps").
		Select(`
            ps.id_product AS product_id,
            pl.name AS name,
            pl.link_rewrite AS link_rewrite,
            CONCAT(?, ims.id_image, '-small_default/', pl.link_rewrite, '.webp') AS image_link,
            cl.name AS category_name,
            p.reference AS reference,
            COALESCE(v.variants_number, 0) AS variants_number,
            sa.quantity AS quantity
        `, config.Get().Image.ImagePrefix).
		Joins("JOIN "+dbmodel.PsProductCols.IDProduct.Tab()+" p ON p.id_product = ps.id_product").
		Joins("JOIN ps_product_lang pl ON pl.id_product = ps.id_product AND pl.id_lang = ?", id_lang).
		Joins("JOIN ps_image_shop ims ON ims.id_product = ps.id_product AND ims.cover = 1").
		Joins("JOIN ps_category_lang cl ON cl.id_category = ps.id_category_default AND cl.id_lang = ?", id_lang).
		Joins("JOIN ps_category_product cp ON cp.id_product = ps.id_product").
		Joins("LEFT JOIN variants v ON v.id_product = ps.id_product").
		Joins("LEFT JOIN ps_stock_available sa ON sa.id_product = ps.id_product AND sa.id_product_attribute = 0").
		Where("ps.active = ?", 1).
		Group("ps.id_product").
		Clauses(exclause.With{CTEs: []exclause.CTE{
			{
				Name:     "variants",
				Subquery: exclause.Subquery{DB: db.Get().Model(&dbmodel.PsProductAttributeShop{}).Select("id_product", "COUNT(*) AS variants_number").Group("id_product")},
			},
		}})

	// Apply all filters
	if filt != nil {
		filt.ApplyAll(query)
	}

	//  run counter first as query is without limit and offset
	err := query.Count(&total).Error
	if err != nil {
		return find.Found[model.ProductInList]{}, err
	}

	err = query.
		Order("ps.id_product DESC").
		Limit(p.Limit()).
		Offset(p.Offset()).
		Find(&list).Error
	if err != nil {
		return find.Found[model.ProductInList]{}, err
	}

	return find.Found[model.ProductInList]{
		Items: list,
		Count: uint(total),
	}, nil
}

func (repo *ListRepo) ListUsers(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.UserInList], error) {
	var list []model.UserInList
	var total int64

	query := db.Get().
		Table("b2b_customers AS users").
		Select(`
			users.id AS id,
			users.email AS email,
			users.first_name AS first_name,
			users.last_name AS last_name,
			users.role AS role
		`)

	// Apply all filters
	if filt != nil {
		filt.ApplyAll(query)
	}

	//  run counter first as query is without limit and offset
	err := query.Count(&total).Error
	if err != nil {
		return find.Found[model.UserInList]{}, err
	}

	err = query.
		Order("users.id DESC").
		Limit(p.Limit()).
		Offset(p.Offset()).
		Find(&list).Error
	if err != nil {
		return find.Found[model.UserInList]{}, err
	}

	return find.Found[model.UserInList]{
		Items: list,
		Count: uint(total),
	}, nil
}
