package controller

import (
	"context"
	"errors"

	"git.schreifuchs.ch/schreifuchs/warehouse/api"
	"git.schreifuchs.ch/schreifuchs/warehouse/model"
	"git.schreifuchs.ch/schreifuchs/warehouse/utils"
	"gorm.io/gorm"
)

func (c *Controller) GetBuckets(ctx context.Context, request api.GetBucketsRequestObject) (api.GetBucketsResponseObject, error) {

	buckets, err := c.db.FindApiBuckets(*request.Params.Limit, *request.Params.Offset)
	if err != nil {
		return nil, err
	}

	t := len(buckets)

	return api.GetBuckets200JSONResponse{
		Items: &buckets,
		Total: &t,
	}, nil
}

func (c *Controller) PostBuckets(ctx context.Context, request api.PostBucketsRequestObject) (api.PostBucketsResponseObject, error) {

	b := &model.Bucket{}
	b.Name = *request.Body.Name

	c.db.InsertBucket(b)

	return api.PostBuckets409Response{}, nil
}

func (c *Controller) DeleteBucketsBucketName(ctx context.Context, request api.DeleteBucketsBucketNameRequestObject) (api.DeleteBucketsBucketNameResponseObject, error) {
	if err := c.db.DeleteBucketByName(request.BucketName); errors.Is(err, gorm.ErrRecordNotFound) {
		return api.DeleteBucketsBucketName404Response{}, nil
	} else if err != nil {
		return nil, err
	}
	return api.DeleteBucketsBucketName204Response{}, nil
}

func (c *Controller) GetBucketsBucketNameObjects(ctx context.Context, request api.GetBucketsBucketNameObjectsRequestObject) (response api.GetBucketsBucketNameObjectsResponseObject, err error) {

	if bucket, err := c.db.FindBucketByName(request.BucketName, *request.Params.Limit, *request.Params.Offset); err == nil {
		objects := make([]api.Object, 0, len(bucket.Objects))

		for _, o := range utils.Paginate(bucket.Objects, *request.Params.Offset, *request.Params.Limit) {
			s := int(o.Size)

			objects = append(objects, api.Object{
				Key:          &o.Key,
				LastModified: &o.UpdatedAt,
				Size:         &s,
			})

		}

		total := len(bucket.Objects)

		return api.GetBucketsBucketNameObjects200JSONResponse{
			Items: &objects,
			Total: &total,
		}, nil
	} else if errors.Is(err, gorm.ErrRecordNotFound) {

		return api.GetBucketsBucketNameObjects404Response{}, nil
	}

	return
}

func (c *Controller) DeleteBucketsBucketNameObjectsObjectKey(ctx context.Context, request api.DeleteBucketsBucketNameObjectsObjectKeyRequestObject) (api.DeleteBucketsBucketNameObjectsObjectKeyResponseObject, error) {
	err := c.db.DeleteObjectByKey(request.BucketName, request.ObjectKey)

	if errors.Is(err, gorm.ErrRecordNotFound) {
		return api.DeleteBucketsBucketNameObjectsObjectKey404Response{}, nil
	}

	return api.DeleteBucketsBucketNameObjectsObjectKey204Response{}, err
}

func (c *Controller) GetBucketsBucketNameObjectsObjectKey(ctx context.Context, request api.GetBucketsBucketNameObjectsObjectKeyRequestObject) (api.GetBucketsBucketNameObjectsObjectKeyResponseObject, error) {
	return api.GetBucketsBucketNameObjectsObjectKey404Response{}, nil
}

func (c *Controller) PutBucketsBucketNameObjectsObjectKey(ctx context.Context, request api.PutBucketsBucketNameObjectsObjectKeyRequestObject) (api.PutBucketsBucketNameObjectsObjectKeyResponseObject, error) {
	return api.PutBucketsBucketNameObjectsObjectKey400Response{}, nil
}
