package database

import (
	"MediaTools/internal/models"
	"MediaTools/internal/schemas/storage"
	"context"
	"fmt"
	"iter"
	"time"

	"gorm.io/gorm"
)

// UpdateMediaTransferHistory 更新媒体转移历史记录
// 如果 ID 不存在则创建新的转移历史记录
// 如果 ID 存在则更新现有的转移历史记录
func UpdateMediaTransferHistory(history *models.MediaTransferHistory) error {
	result := db.Save(history)
	if result.Error != nil {
		return fmt.Errorf("更新数据库失败: %w", result.Error)
	}
	return nil
}

func QueryMediaTransferHistoryBySrc(src storage.StoragePath) (*models.MediaTransferHistory, error) {
	ctx := context.Background()
	history, err := gorm.G[models.MediaTransferHistory](db).Where("src_type = ? AND src_path = ?", src.GetStorageType(), src.GetPath()).First(ctx)
	if err != nil {
		return nil, err
	}
	return &history, nil
}

func QueryMediaTransferHistoryByID(ctx context.Context, id uint64) (*models.MediaTransferHistory, error) {
	history, err := gorm.G[models.MediaTransferHistory](db).Where("id = ?", id).First(ctx)
	if err != nil {
		return nil, err
	}
	return &history, nil
}

// QueryMediaTransferHistory 查询媒体转移历史记录
// 支持根据 ID、时间范围、源路径、目标路径、转移类型和状态进行过滤
// 如果 ID 不为 nil，则只查询该 ID 的记录
// 如果 ID 为 nil，则根据其他条件查询
func QueryMediaTransferHistory(
	ctx context.Context,
	startTime *time.Time, endTime *time.Time,
	storageType storage.StorageType, // 存储类型和路径，存储类型为 StorageUnknown 时不进行过滤，否则对 src 和 dst 都进行过滤
	path string, // 路径，模糊匹配
	transferType storage.TransferType, // 转移类型为 TransferUnknown 时不进行过滤
	status *bool, // 是否成功
	offset int, // 偏移量
) (iter.Seq2[*models.MediaTransferHistory, error], error) {
	query := db.Model(&models.MediaTransferHistory{}).WithContext(ctx)

	switch {
	case startTime != nil && endTime != nil: // 如果同时提供了开始和结束时间
		query = query.Where("created_at BETWEEN ? AND ?", *startTime, *endTime)
	case startTime != nil: // 如果只提供了开始时间
		query = query.Where("created_at >= ?", *startTime)
	case endTime != nil: // 如果只提供了结束时间
		query = query.Where("created_at <= ?", *endTime)
	}

	if storageType != storage.StorageUnknown {
		query = query.Where("src_type = ? OR dst_type = ?", storageType, storageType)
	}
	if path != "" {
		query = query.Where("src_path LIKE ? OR dst_path LIKE ?", "%"+path+"%", "%"+path+"%")
	}

	if transferType != storage.TransferUnknown {
		query = query.Where("transfer_type = ?", transferType)
	}

	if status != nil {
		query = query.Where("status = ?", *status)
	}

	if offset > 0 {
		query = query.Offset(offset)
	}

	rows, err := query.Rows()
	if err != nil {
		return nil, fmt.Errorf("查询媒体转移历史记录失败: %w", err)
	}
	return func(yield func(*models.MediaTransferHistory, error) bool) {
		defer rows.Close()

		var history models.MediaTransferHistory
		for rows.Next() {
			err := db.ScanRows(rows, &history)
			if err != nil {
				if !yield(nil, fmt.Errorf("扫描媒体转移历史记录失败: %w", err)) {
					return
				}
				continue
			}
			if !yield(&history, nil) {
				return
			}
		}

		// 检查是否有错误发生
		if err := rows.Err(); err != nil {
			yield(nil, fmt.Errorf("遍历结果集时发生错误: %w", err))
		}
	}, nil
}

func DeleteMediaTransferHistory(ctx context.Context, id uint64) error {
	rowsAffected, err := gorm.G[models.MediaTransferHistory](db).Where("id = ?", id).Delete(ctx)
	if err != nil {
		return fmt.Errorf("删除媒体转移历史记录失败: %w", err)
	}
	if rowsAffected == 0 {
		return fmt.Errorf("未找到媒体转移历史记录: %d", id)
	}
	return nil
}
