package example

import (
	"context"
	"errors"

	"kra/internal/biz/example"
	"kra/internal/data/model"

	"gorm.io/gorm"
)

type breakpointContinueRepo struct {
	db *gorm.DB
}

// NewBreakpointContinueRepo 创建断点续传仓储
func NewBreakpointContinueRepo(db *gorm.DB) example.BreakpointContinueRepo {
	return &breakpointContinueRepo{db: db}
}

// FindOrCreateFile 查找或创建文件记录
func (r *breakpointContinueRepo) FindOrCreateFile(ctx context.Context, fileMd5, fileName string, chunkTotal int) (*example.ExaFile, error) {
	var file model.ExaFile
	cfile := model.ExaFile{
		FileMd5:    fileMd5,
		FileName:   fileName,
		ChunkTotal: int64(chunkTotal),
	}

	// 检查是否已有完成的文件
	if errors.Is(r.db.WithContext(ctx).Where("file_md5 = ? AND is_finish = ?", fileMd5, true).First(&file).Error, gorm.ErrRecordNotFound) {
		// 没有完成的文件，查找或创建
		err := r.db.WithContext(ctx).Where("file_md5 = ? AND file_name = ?", fileMd5, fileName).
			FirstOrCreate(&file, cfile).Error
		if err != nil {
			return nil, err
		}
		// 加载切片
		var chunks []model.ExaFileChunk
		r.db.WithContext(ctx).Where("exa_file_id = ?", file.ID).Find(&chunks)
		return toBizExaFileWithChunks(&file, chunks), nil
	}

	// 已有完成的文件，创建新记录
	cfile.IsFinish = true
	cfile.FilePath = file.FilePath
	if err := r.db.WithContext(ctx).Create(&cfile).Error; err != nil {
		return nil, err
	}
	return toBizExaFileWithChunks(&cfile, nil), nil
}

// CreateFileChunk 创建文件切片记录
func (r *breakpointContinueRepo) CreateFileChunk(ctx context.Context, fileID uint, fileChunkPath string, fileChunkNumber int) error {
	chunk := model.ExaFileChunk{
		ExaFileID:       int64(fileID),
		FileChunkPath:   fileChunkPath,
		FileChunkNumber: int64(fileChunkNumber),
	}
	return r.db.WithContext(ctx).Create(&chunk).Error
}

// DeleteFileChunk 删除文件切片记录
func (r *breakpointContinueRepo) DeleteFileChunk(ctx context.Context, fileMd5, filePath string) error {
	var file model.ExaFile
	err := r.db.WithContext(ctx).Where("file_md5 = ?", fileMd5).First(&file).
		Updates(map[string]interface{}{
			"is_finish": true,
			"file_path": filePath,
		}).Error
	if err != nil {
		return err
	}

	return r.db.WithContext(ctx).Where("exa_file_id = ?", file.ID).Delete(&model.ExaFileChunk{}).Unscoped().Error
}

// 转换函数
func toBizExaFileWithChunks(m *model.ExaFile, chunks []model.ExaFileChunk) *example.ExaFile {
	file := &example.ExaFile{
		ID:         uint(m.ID),
		FileName:   m.FileName,
		FileMd5:    m.FileMd5,
		FilePath:   m.FilePath,
		ChunkTotal: int(m.ChunkTotal),
		IsFinish:   m.IsFinish,
	}
	if len(chunks) > 0 {
		file.ExaFileChunk = make([]example.ExaFileChunk, len(chunks))
		for i, chunk := range chunks {
			file.ExaFileChunk[i] = example.ExaFileChunk{
				ID:              uint(chunk.ID),
				ExaFileID:       uint(chunk.ExaFileID),
				FileChunkNumber: int(chunk.FileChunkNumber),
				FileChunkPath:   chunk.FileChunkPath,
			}
		}
	}
	return file
}
