package db

import (
	"fmt"
	"time"

	"gitlink.org.cn/cloudream/jcs-pub/client/types"
	"gorm.io/gorm"
)

type BucketDB struct {
	*DB
}

func (db *DB) Bucket() *BucketDB {
	return &BucketDB{DB: db}
}

func (db *BucketDB) GetByID(ctx SQLContext, bucketID types.BucketID) (types.Bucket, error) {
	var ret types.Bucket
	err := ctx.Table("Bucket").Where("BucketID = ?", bucketID).First(&ret).Error
	return ret, err
}

func (db *BucketDB) GetByName(ctx SQLContext, bucketName string) (types.Bucket, error) {
	var ret types.Bucket
	err := ctx.Table("Bucket").Where("Name = ?", bucketName).First(&ret).Error
	return ret, err
}

func (*BucketDB) GetAll(ctx SQLContext) ([]types.Bucket, error) {
	var ret []types.Bucket
	err := ctx.Table("Bucket").Find(&ret).Error
	return ret, err
}

func (db *BucketDB) Create(ctx SQLContext, bucketName string, createTime time.Time) (types.Bucket, error) {
	var bucketID int64
	err := ctx.Table("Bucket").
		Select("Bucket.BucketID").
		Where("Bucket.Name = ?", bucketName).
		Scan(&bucketID).Error

	if err != nil {
		return types.Bucket{}, err
	}

	if bucketID > 0 {
		return types.Bucket{}, gorm.ErrDuplicatedKey
	}

	newBucket := types.Bucket{Name: bucketName, CreateTime: createTime}
	if err := ctx.Table("Bucket").Create(&newBucket).Error; err != nil {
		return types.Bucket{}, fmt.Errorf("insert bucket failed, err: %w", err)
	}

	return newBucket, nil
}

func (db *BucketDB) Rename(ctx SQLContext, bucketID types.BucketID, bucketName string) error {
	return ctx.Table("Bucket").Where("BucketID = ?", bucketID).Update("Name", bucketName).Error
}

func (db *BucketDB) Delete(ctx SQLContext, bucketID types.BucketID) error {
	return ctx.Delete(&types.Bucket{}, "BucketID = ?", bucketID).Error
}

func (db *BucketDB) DeleteComplete(tx SQLContext, bucketID types.BucketID) error {
	pkgs, err := db.Package().GetBucketPackages(tx, bucketID)
	if err != nil {
		return err
	}

	for _, pkg := range pkgs {
		err := db.Package().DeleteComplete(tx, pkg.PackageID)
		if err != nil {
			return err
		}
	}
	return db.Bucket().Delete(tx, bucketID)
}
