// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2

package file

import (
	"context"
	"time"

	"github.com/perfect-panel/server/internal/svc"
	"github.com/perfect-panel/server/internal/types"
	"github.com/perfect-panel/server/pkg/logger"
	"github.com/perfect-panel/server/pkg/xerr"
	"github.com/pkg/errors"
)

type FileUploadCompleteLogic struct {
	logger.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// Complete file upload
func NewFileUploadCompleteLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FileUploadCompleteLogic {
	return &FileUploadCompleteLogic{
		Logger: logger.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *FileUploadCompleteLogic) FileUploadComplete(req *types.FileUploadCompleteRequest) (resp *types.FileUploadCompleteResponse, err error) {
	u, err := currentUserFromContext(l.ctx)
	if err != nil {
		return nil, err
	}

	meta, err := loadUploadMeta(l.ctx, l.svcCtx, req.FileId)
	if err != nil {
		return nil, err
	}
	if meta.UserID != u.Id {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
	}

	head, err := l.svcCtx.S3Store.HeadObject(l.ctx, meta.ObjectKey)
	if err != nil {
		l.Errorw("head object failed", logger.Field("error", err.Error()), logger.Field("file_id", meta.FileID))
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "uploaded file not found")
	}
	if meta.Size > 0 && head.ContentLength != meta.Size {
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "uploaded file size mismatch")
	}

	meta.Status = fileUploadCompleteStatus
	meta.Etag = head.ETag
	meta.ContentType = head.ContentType
	meta.CompletedAt = time.Now().Unix()
	if err := saveUploadMeta(l.ctx, l.svcCtx, meta, 7*24*time.Hour); err != nil {
		return nil, err
	}

	return &types.FileUploadCompleteResponse{
		FileId:      meta.FileID,
		ObjectKey:   meta.ObjectKey,
		Size:        head.ContentLength,
		ContentType: head.ContentType,
		Etag:        head.ETag,
		Status:      meta.Status,
	}, nil
}
