package location

import (
	"context"
	"strconv"
	"strings"

	"github.com/UpmeshLTD/urus-aio/infrastructure/db/entities"
	"github.com/UpmeshLTD/urus-aio/mdm/db/gormdb"
)

type Repository interface {
	GetCountries(ctx context.Context) ([]*entities.Country, error)
	GetCountryByID(ctx context.Context, countryID int64) (*entities.Country, error)
	GetCountryByCode(ctx context.Context, countryCode string) (*entities.Country, error)
	GetLocations(ctx context.Context, params *entities.GetLocationsFilterParams) ([]*entities.Location, error)
}

type repositoryImpl struct {
	db gormdb.GormDB
}

func NewRepository(db gormdb.GormDB) Repository {
	return &repositoryImpl{
		db: db,
	}
}

func (r *repositoryImpl) GetCountries(ctx context.Context) ([]*entities.Country, error) {
	var countries []*entities.Country
	if err := r.db.DB().Find(&countries).Error; err != nil {
		return nil, err
	}
	return countries, nil
}

func (r *repositoryImpl) GetCountryByID(ctx context.Context, countryID int64) (*entities.Country, error) {
	country := &entities.Country{}
	if err := r.db.DB().First(country, "id = ?", countryID).Error; err != nil {
		return nil, err
	}
	return country, nil
}

func (r *repositoryImpl) GetCountryByCode(ctx context.Context, countryCode string) (*entities.Country, error) {
	country := &entities.Country{}
	if err := r.db.DB().First(country, "code like ?", strings.ToUpper(countryCode)).Error; err != nil {
		return nil, err
	}
	return country, nil
}

func (r *repositoryImpl) GetLocations(ctx context.Context, params *entities.GetLocationsFilterParams) ([]*entities.Location, error) {
	var locations []*entities.Location

	query := r.db.DB().Model(&entities.Location{})
	if params != nil {
		if len(params.CountryID) > 0 {
			countryId, _ := strconv.ParseInt(params.CountryID, 10, 64)
			query = query.Joins("join countries on locations.country_id = countries.id").Where("country_id = ? OR countries.code like ?", countryId, strings.ToUpper(params.CountryID))
		}
		if params.ParentID != 0 {
			query = query.Where("parent_id = ?", params.ParentID)
		} else {
			query = query.Where("parent_id IS NULL")
		}
	}

	query = query.Order("locations.international_name ASC")

	if err := query.Find(&locations).Error; err != nil {
		return nil, err
	}
	return locations, nil
}
