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"
)

type SubscriptionTypesInterface interface {
	Delete(subtype *common.SubscriptionType) (orm.Result, error)
	Insert(subtype *common.SubscriptionType) (orm.Result, error)
	Update(subtype *common.SubscriptionType) (orm.Result, error)
	Select(filter *common.SubscriptionType) ([]common.SubscriptionType, error)
	Load(subtype *common.SubscriptionType) error
	Count(filter *common.SubscriptionType) (int, error)
}

type SubscriptionTypes struct {
	QueryBase
}

// Select returns list of drivers
func (st *SubscriptionTypes) Select(filter *common.SubscriptionType) ([]common.SubscriptionType, error) {
	subtypes := []common.SubscriptionType{}
	query := st.GetDBConn().Model(&subtypes)

	st.selectFilter(query, filter)

	err := query.Select()

	return subtypes, errors.WithStack(err)
}

func (st *SubscriptionTypes) selectFilter(query *orm.Query, filter *common.SubscriptionType) {
	if filter.ID != uuid.Nil {
		query.Where("ID = ?", filter.ID)
	}
}

func (st *SubscriptionTypes) Insert(subtype *common.SubscriptionType) (orm.Result, error) {
	return st.insert(subtype)
}

func (st *SubscriptionTypes) Update(subtype *common.SubscriptionType) (orm.Result, error) {
	err := st.validateSubTypeID(subtype)
	if err != nil {
		return nil, err
	}

	return st.GetDBConn().Model(subtype).Column("name", "destination", "price", "currency", "description", "duration_value", "duration_unit").WherePK().Update()
}

func (st *SubscriptionTypes) Delete(subtype *common.SubscriptionType) (orm.Result, error) {
	err := st.validateSubTypeID(subtype)
	if err != nil {
		return nil, err
	}

	tx, err := st.GetDBConn().Begin()
	if err != nil {
		return nil, err
	}
	defer tx.Close()

	subscriptions := common.Subscription{
		SubscriptionTypeID: subtype.ID,
	}
	_, err = tx.Model(&subscriptions).Where("subscription_type_id = ?subscription_type_id").Delete()
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	result, err := tx.Model(subtype).WherePK().Delete()
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	tx.Commit()

	return result, err
}

func (st *SubscriptionTypes) Load(subtype *common.SubscriptionType) error {
	query := st.GetDBConn().Model(subtype)

	if subtype.ID != uuid.Nil {
		query.WherePK()
	} else if subtype.Name != "" {
		query.Where("name = ?name")
	} else {
		return errors.New("no id or name")
	}

	return query.Select()
}

func (st *SubscriptionTypes) Count(filter *common.SubscriptionType) (int, error) {
	query := st.GetDBConn().Model((*common.SubscriptionType)(nil))

	st.selectFilter(query, filter)

	return query.Count()
}

func (st *SubscriptionTypes) validateSubTypeID(subtype *common.SubscriptionType) error {
	if subtype.ID == uuid.Nil {
		return errors.WithStack(&validator.FieldError{
			ErrorMsg: "ID required",
		})
	}

	return nil
}
