package customerRepo

import (
	"strings"

	"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/utils/query/filters"
	"git.ma-al.com/goc_daniel/b2b/app/utils/query/find"
)

type UICustomerRepo interface {
	Get(id uint) (*model.Customer, error)
	GetByEmail(email string) (*model.Customer, error)
	GetByExternalProviderId(provider model.AuthProvider, id string) (*model.Customer, error)
	Find(langId uint, p find.Paging, filt *filters.FiltersList, search string) (*find.Found[model.UserInList], error)
	Save(customer *model.Customer) error
	Create(customer *model.Customer) error
}

type CustomerRepo struct{}

func New() UICustomerRepo {
	return &CustomerRepo{}
}

func (repo *CustomerRepo) Get(id uint) (*model.Customer, error) {
	var customer model.Customer

	err := db.DB.
		Preload("Role.Permissions").
		First(&customer, id).
		Error

	return &customer, err
}

func (repo *CustomerRepo) GetByEmail(email string) (*model.Customer, error) {
	var customer model.Customer

	err := db.DB.
		Preload("Role.Permissions").
		Where("email = ?", email).
		First(&customer).
		Error

	return &customer, err
}

func (repo *CustomerRepo) GetByExternalProviderId(provider model.AuthProvider, id string) (*model.Customer, error) {
	var customer model.Customer

	err := db.DB.
		Preload("Role.Permissions").
		Where("provider = ? AND provider_id = ?", provider, id).
		First(&customer).
		Error

	return &customer, err
}

func (repo *CustomerRepo) Find(langId uint, p find.Paging, filt *filters.FiltersList, search string) (*find.Found[model.UserInList], error) {

	query := db.DB.
		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
		`)

	if search != "" {
		words := strings.Fields(search)
		if len(words) > 5 {
			words = words[:5]
		}
		var conditions []string
		var args []interface{}
		for _, word := range words {

			conditions = append(conditions, `
			(LOWER(first_name) LIKE ? OR
			 LOWER(last_name) LIKE ? OR
			 LOWER(email) LIKE ?)
		`)

			for range 3 {
				args = append(args, "%"+strings.ToLower(word)+"%")
			}
		}

		conditionsQuery := strings.Join(conditions, " AND ")

		query = query.Where(conditionsQuery, args...)

	}

	query = query.Scopes(filt.All()...)

	found, err := find.Paginate[model.UserInList](langId, p, query)

	return &found, err
}

func (repo *CustomerRepo) Save(customer *model.Customer) error {
	return db.DB.Save(customer).Error
}

func (repo *CustomerRepo) Create(customer *model.Customer) error {
	return db.DB.Create(customer).Error
}

// func (repo *CustomerRepo) Search(
// 	customerId uint,
// 	partnerCode string,
// 	p find.Paging,
// 	filt *filters.FiltersList,
// 	search string,
// ) (found find.Found[model.UserInList], err error) {
// 	words := strings.Fields(search)
// 	if len(words) > 5 {
// 		words = words[:5]
// 	}

// 	query := ctx.DB().
// 		Model(&model.Customer{}).
// 		Select("customer.id AS id, customer.first_name as first_name, customer.last_name as last_name, customer.phone_number AS phone_number, customer.email AS email, count(distinct investment_plan_contract.id) as iiplan_purchases, count(distinct `order`.id) as single_purchases, entity.name as entity_name").
// 		Where("customer.id <> ?", customerId).
// 		Where("(customer.id IN (SELECT id FROM customer WHERE partner_code IN (WITH RECURSIVE partners AS (SELECT code AS dst FROM partner WHERE code = ? UNION SELECT code FROM partner JOIN partners ON partners.dst = partner.superior_code) SELECT dst FROM partners)) OR customer.recommender_code = ?)", partnerCode, partnerCode).
// 		Scopes(view.CustomerListQuery())

// 	var conditions []string
// 	var args []interface{}
// 	for _, word := range words {

// 		conditions = append(conditions, `
// 			(LOWER(first_name) LIKE ? OR
// 			 LOWER(last_name) LIKE ? OR
// 			 phone_number LIKE ? OR
// 			 LOWER(email) LIKE ?)
// 		`)

// 		for i := 0; i < 4; i++ {
// 			args = append(args, "%"+strings.ToLower(word)+"%")
// 		}
// 	}

// 	finalQuery := strings.Join(conditions, " AND ")

// 	query = query.Where(finalQuery, args...).
// 		Scopes(filt.All()...)

// 	found, err = find.Paginate[V](ctx, p, query)

// 	return found, errs.Recorded(span, err)
// }

// 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
// }
