package model

import (
	"time"

	"github.com/pingcap/errors"
	"gorm.io/gorm"

	"github.com/pingcap-inc/clinic/pkg/db"
	"github.com/pingcap-inc/clinic/pkg/pagination"
)

func AddCredential(orgID, userID uint, hashedKey string) (*db.Credential, error) {
	c := db.Credential{
		Model: gorm.Model{
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		},
		OrgID:  orgID,
		UserID: userID,
		// Name:      name,
		HashedKey: hashedKey,
	}
	err := db.Transaction(func(tx *gorm.DB) error {
		return tx.Create(&c).Error
	})

	return &c, err
}

func DeleteCredential(id uint) error {
	return db.Transaction(func(tx *gorm.DB) error {
		_, err := db.NewCredentialQuerySet(tx).IDEq(id).DeleteNumUnscoped()
		return err
	})
}

func DeleteCredentialByUserID(userID uint) error {
	return db.Transaction(func(tx *gorm.DB) error {
		_, err := db.NewCredentialQuerySet(tx).UserIDEq(userID).DeleteNumUnscoped()
		return err
	})
}

func GetCredential(id uint) (*db.Credential, error) {
	var (
		credential db.Credential
		err        error
	)
	err = db.Transaction(func(tx *gorm.DB) error {
		return db.NewCredentialQuerySet(tx).
			IDEq(id).
			One(&credential)
	})

	return &credential, err
}

func ListCredentials(orgID, userID uint, page, perPage int) ([]db.Credential, int64, error) {
	var (
		credentials []db.Credential
		total       int64
		err         error
	)

	err = db.Transaction(func(tx *gorm.DB) error {
		qs := db.NewCredentialQuerySet(tx).
			OrgIDEq(orgID).UserIDEq(userID)

		if perPage > 0 {
			if total, err = qs.Count(); err != nil {
				return errors.Annotate(err, "count credentials error")
			}

			startIndex := pagination.GetStartIndex(page, perPage)
			qs = qs.Limit(perPage).Offset(startIndex)
		}

		if err := qs.All(&credentials); err != nil {
			return errors.Annotate(err, "fetch credentials failed")
		}

		if perPage <= 0 {
			// no pagination
			total = int64(len(credentials))
		}

		return nil
	})
	if err != nil {
		return nil, 0, err
	}

	return credentials, total, nil
}

func ListAPICredentials(userID uint, page, perPage int) ([]db.APICredential, int64, error) {
	var (
		credentials []db.APICredential
		total       int64
		err         error
	)

	err = db.Transaction(func(tx *gorm.DB) error {
		q := tx.Model(&db.APICredential{}).Where("user_id=?", userID)
		if perPage > 0 {
			if err = q.Count(&total).Error; err != nil {
				return errors.Annotate(err, "count api credentials error")
			}

			startIndex := pagination.GetStartIndex(page, perPage)
			q = q.Limit(perPage).Offset(startIndex)
		}
		if err := q.Find(&credentials).Error; err != nil {
			return errors.Annotate(err, "fetch api credentials failed")
		}
		if perPage <= 0 {
			// no pagination
			total = int64(len(credentials))
		}
		return nil
	})
	if err != nil {
		return nil, 0, err
	}

	return credentials, total, nil
}
