package queries

import (
	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/validator"

	"github.com/go-pg/pg/v10/orm"
	"github.com/google/uuid"
	"github.com/pkg/errors"
)

var subFeaturesCols = []string{}

type SubscriptionFeaturesInterface interface {
	Delete(model *common.SubscriptionFeature) (orm.Result, error)
	Insert(model *common.SubscriptionFeature) (orm.Result, error)
	Update(model *common.SubscriptionFeature) (orm.Result, error)
	Count(filter *common.SubscriptionFeature) (int, error)
	Select(fitler *common.SubscriptionFeature, paging *PageQueryOptions) ([]common.SubscriptionFeature, error)
	Load(model *common.SubscriptionFeature) error
}

type SubscriptionFeatures struct {
	QueryBase
}

func (sf *SubscriptionFeatures) Delete(model *common.SubscriptionFeature) (orm.Result, error) {
	var err error
	total := &ORMResults{}
	tx, err := sf.GetDBConn().Begin()
	if err != nil {
		return total, errors.WithStack(err)
	}
	defer func() {
		if err != nil {
			tx.Rollback()
		}
		tx.Close()
	}()

	result, err := tx.Model(&common.SubscriptionConfiguration{SubscriptionFeatureID: model.ID}).Where("subscription_feature_id = ?subscription_feature_id").Delete()
	if err != nil {
		return total, errors.WithStack(err)
	}
	total.AddResult(result)

	result, err = tx.Model(model).WherePK().Delete()
	if err != nil {
		return total, errors.WithStack(err)
	}
	total.AddResult(result)

	err = tx.Commit()
	if err != nil {
		return total, errors.WithStack(err)
	}

	return total, nil
}

func (sf *SubscriptionFeatures) Insert(model *common.SubscriptionFeature) (orm.Result, error) {
	return sf.insert(model)
}

func (sf *SubscriptionFeatures) Update(model *common.SubscriptionFeature) (orm.Result, error) {
	err := validator.ValidateStruct(model)
	if err != nil {
		return nil, errors.WithStack(err)
	}

	return sf.resultWithStack(sf.GetDBConn().Model(model).Column(subFeaturesCols...).WherePK().Update())
}

func (sf *SubscriptionFeatures) Count(filter *common.SubscriptionFeature) (int, error) {
	query := sf.GetDBConn().Model(filter)

	sf.selectFilter(query, filter)

	count, err := query.Count()

	return count, errors.WithStack(err)
}

func (sf *SubscriptionFeatures) Load(model *common.SubscriptionFeature) error {
	var err error

	tx, err := sf.GetDBConn().Begin()
	if err != nil {
		return errors.WithStack(err)
	}
	defer func() {
		if err != nil {
			tx.Rollback()
		}
		tx.Close()
	}()

	err = tx.Model(model).WherePK().First()
	if err != nil {
		return errors.WithStack(err)
	}

	configs := []common.SubscriptionConfiguration{}
	err = tx.Model(&configs).Where("subscription_feature_id = ?", model.ID).Select()
	if err != nil {
		return errors.WithStack(err)
	}
	model.Configurations = configs

	err = tx.Commit()

	return errors.WithStack(err)
}

func (sf *SubscriptionFeatures) selectFilter(query *orm.Query, filter *common.SubscriptionFeature) {
	if filter.ID != uuid.Nil {
		query.Where("ID = ?", filter.ID)
	}

	if filter.Name != "" {
		query.Where("name = ?", filter.Name)
	}

	if filter.Description != "" {
		query.Where("description = ?", filter.Description)
	}
}

func (sf *SubscriptionFeatures) Select(filter *common.SubscriptionFeature, paging *PageQueryOptions) ([]common.SubscriptionFeature, error) {
	items := []common.SubscriptionFeature{}
	query := sf.GetDBConn().Model(&items)

	sf.selectFilter(query, filter)
	if paging != nil {
		sf.pageQuery(query, paging)
	}

	err := query.Select()

	return items, errors.WithStack(err)
}
