package delivery_plan

import (
	"context"

	"gorm.io/gorm/clause"

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

	"github.com/UpmeshLTD/urus-aio/shipment/db/gormdb"
)

type Repository interface {
	GetDeliveryPlans(ctx context.Context, params *entities.GetDeliveryPlansFilterParams) ([]*entities.CourierDeliveryPlan, error)
	CreateDeliveryPlan(ctx context.Context, entity *entities.CourierDeliveryPlan) (*entities.CourierDeliveryPlan, error)
	UpdateDeliveryPlan(ctx context.Context, id entities.ID, entity *entities.CourierDeliveryPlan) error
	DeleteDeliveryPlan(ctx context.Context, id entities.ID) error
}

type repositoryImpl struct {
	db gormdb.GormDB
}

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

func (r *repositoryImpl) GetDeliveryPlans(ctx context.Context, params *entities.GetDeliveryPlansFilterParams) ([]*entities.CourierDeliveryPlan, error) {
	var (
		results []*entities.CourierDeliveryPlan
		builder = r.db.DB().Model(&entities.CourierDeliveryPlan{})
	)

	if params != nil {
		if params.CountryID != 0 {
			builder = builder.Where("country_id = ?", params.CountryID)
		}

		if params.CourierID != 0 {
			builder = builder.Where("courier_id = ?", params.CourierID)
		}

		if !params.Deactivate {
			builder = builder.Where("deactivate = false")
		}
	}

	if err := builder.Preload(clause.Associations).Find(&results).Error; err != nil {
		return nil, err
	}
	return results, nil
}

func (r *repositoryImpl) CreateDeliveryPlan(ctx context.Context, entity *entities.CourierDeliveryPlan) (*entities.CourierDeliveryPlan, error) {
	if err := r.db.DB().Model(&entities.CourierDeliveryPlan{}).Create(&entity).Error; err != nil {
		return nil, err
	}

	return entity, nil
}

func (r *repositoryImpl) UpdateDeliveryPlan(ctx context.Context, id entities.ID, entity *entities.CourierDeliveryPlan) error {
	if err := r.db.DB().Model(&entities.CourierDeliveryPlan{}).Where("id = ?", id.ToInt64()).Updates(&entity).Error; err != nil {
		return err
	}

	return nil
}

func (r *repositoryImpl) DeleteDeliveryPlan(ctx context.Context, id entities.ID) error {
	if err := r.db.DB().Delete(&entities.CourierDeliveryPlan{}, id).Error; err != nil {
		return err
	}

	return nil
}
