package mysql

import (
	"context"
	"time"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"

	filemanager "wucher/internal/domain/file_manager"
)

func (r *FileManagerFileRepository) CreateUploadIntent(ctx context.Context, row *filemanager.FileUploadIntent) error {
	return r.db.WithContext(ctx).Create(row).Error
}

func (r *FileManagerFileRepository) GetUploadIntentByID(ctx context.Context, id []byte) (*filemanager.FileUploadIntent, error) {
	var row filemanager.FileUploadIntent
	err := r.db.WithContext(ctx).Where("id = ?", id).First(&row).Error
	if err == nil {
		return &row, nil
	}
	if err == gorm.ErrRecordNotFound {
		return nil, nil
	}
	return nil, err
}

func (r *FileManagerFileRepository) GetUploadIntentByIDForUpdate(ctx context.Context, id []byte) (*filemanager.FileUploadIntent, error) {
	var row filemanager.FileUploadIntent
	err := r.db.WithContext(ctx).
		Clauses(clause.Locking{Strength: "UPDATE"}).
		Where("id = ?", id).
		First(&row).Error
	if err == nil {
		return &row, nil
	}
	if err == gorm.ErrRecordNotFound {
		return nil, nil
	}
	return nil, err
}

func (r *FileManagerFileRepository) MarkUploadIntentCompleted(ctx context.Context, params filemanager.FileUploadIntentCompleteParams) error {
	completedAt := params.CompletedAt
	if completedAt.IsZero() {
		completedAt = time.Now().UTC()
	}

	res := r.db.WithContext(ctx).
		Model(&filemanager.FileUploadIntent{}).
		Where("id = ? AND status = ?", params.ID, filemanager.FileUploadIntentStatusPending).
		Updates(map[string]any{
			"status":       filemanager.FileUploadIntentStatusCompleted,
			"completed_at": completedAt.UTC(),
			"updated_by":   params.UpdatedBy,
			"updated_at":   completedAt.UTC(),
		})
	if res.Error != nil {
		return res.Error
	}
	if res.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	return nil
}

func (r *FileManagerFileRepository) MarkUploadIntentExpired(ctx context.Context, params filemanager.FileUploadIntentExpireParams) error {
	expiredAt := params.ExpiredAt
	if expiredAt.IsZero() {
		expiredAt = time.Now().UTC()
	}

	res := r.db.WithContext(ctx).
		Model(&filemanager.FileUploadIntent{}).
		Where("id = ? AND status = ?", params.ID, filemanager.FileUploadIntentStatusPending).
		Updates(map[string]any{
			"status":     filemanager.FileUploadIntentStatusExpired,
			"updated_by": params.UpdatedBy,
			"updated_at": expiredAt.UTC(),
		})
	if res.Error != nil {
		return res.Error
	}
	if res.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	return nil
}

func (r *FileManagerFileRepository) UpdateUploadIntentSize(ctx context.Context, params filemanager.FileUploadIntentSizeUpdateParams) error {
	res := r.db.WithContext(ctx).
		Model(&filemanager.FileUploadIntent{}).
		Where("id = ? AND status = ?", params.ID, filemanager.FileUploadIntentStatusPending).
		Updates(map[string]any{
			"size_bytes": params.SizeBytes,
			"updated_by": params.UpdatedBy,
			"updated_at": time.Now().UTC(),
		})
	if res.Error != nil {
		return res.Error
	}
	if res.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	return nil
}
