package queries

import (
	"github.com/fiskerinc/cloud-services/pkg/common"
	s "github.com/fiskerinc/cloud-services/pkg/security"
	"github.com/go-pg/pg/v10/orm"
)

type SupplierOrganizationsInterface interface {
	Count(account *common.SupplierOrganization) (int, error)
	Insert(supplierOrganization *common.SupplierOrganization) (orm.Result, error)
	Select(account *common.SupplierOrganization, paging *PageQueryOptions) ([]common.SupplierOrganization, error)
}

type SupplierOrganization struct {
	QueryBase
}

func (so *SupplierOrganization) Count(supplierOrganization *common.SupplierOrganization) (int, error) {
	return so.count(supplierOrganization)
}

func (so *SupplierOrganization) Insert(supplierOrganization *common.SupplierOrganization) (orm.Result, error) {
	enc := s.Encrypt{}
	encryptor, err := enc.GetEncryptor()
	if err != nil {
		return nil, err
	}

	supplierOrganization.PubKey.SetBytes(encryptor.EncryptChunk(supplierOrganization.PubKey.Bytes()))
	supplierOrganization.PrivKey.SetBytes(encryptor.EncryptChunk(supplierOrganization.PrivKey.Bytes()))

	return so.GetDBConn().Model(supplierOrganization).Insert()
}

func (so *SupplierOrganization) Select(filter *common.SupplierOrganization, paging *PageQueryOptions) ([]common.SupplierOrganization, error) {
	supplierOrganizations := []common.SupplierOrganization{}
	query := so.GetDBConn().Model(&supplierOrganizations)

	so.selectFilter(query, filter)

	if paging != nil {
		so.pageQuery(query, paging)
	}

	err := query.Select()

	for _, supplierOrganization := range supplierOrganizations {
		err = so.decryptSupplierOrganization(&supplierOrganization)
		if err != nil {
			return nil, err
		}
	}

	return supplierOrganizations, err
}

func (sf *SupplierOrganization) selectFilter(query *orm.Query, filter *common.SupplierOrganization) {
	if filter.DomainName != "" {
		query.Where("domain_name = ?", filter.DomainName)
	}

	if filter.SupplierOrganizationID != 0 {
		query.Where("supplier_organization_id = ?", filter.SupplierOrganizationID)
	}
}

func (si *SupplierOrganization) decryptSupplierOrganization(supplierOrganization *common.SupplierOrganization) error {
	enc := s.Encrypt{}
	encryptor, err := enc.GetEncryptor()
	if err != nil {
		return err
	}

	if supplierOrganization.PubKey != nil {
		key, err := encryptor.DecryptChunk(supplierOrganization.PubKey.Bytes())
		if err != nil {
			return err
		}
		supplierOrganization.PubKey.SetBytes(key)
	}

	if supplierOrganization.PrivKey != nil {
		key, err := encryptor.DecryptChunk(supplierOrganization.PrivKey.Bytes())
		if err != nil {
			return err
		}
		supplierOrganization.PrivKey.SetBytes(key)
	}

	return nil
}
