package example

import (
	"context"

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

	"gorm.io/gorm"
)

type fileUploadRepo struct {
	db *gorm.DB
}

// NewFileUploadRepo 创建文件上传仓储
func NewFileUploadRepo(db *gorm.DB) example.FileUploadRepo {
	return &fileUploadRepo{db: db}
}

func (r *fileUploadRepo) Create(ctx context.Context, file *example.FileUpload) error {
	m := toFileUploadModel(file)
	return r.db.WithContext(ctx).Create(m).Error
}

func (r *fileUploadRepo) Update(ctx context.Context, file *example.FileUpload) error {
	return r.db.WithContext(ctx).Model(&model.ExaFileUploadAndDownload{}).
		Where("id = ?", file.ID).
		Updates(map[string]any{
			"name":     file.Name,
			"class_id": file.ClassId,
		}).Error
}

func (r *fileUploadRepo) Delete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Unscoped().
		Where("id = ?", id).
		Delete(&model.ExaFileUploadAndDownload{}).Error
}

func (r *fileUploadRepo) FindByID(ctx context.Context, id uint) (*example.FileUpload, error) {
	f := query.ExaFileUploadAndDownload
	m, err := f.WithContext(ctx).Where(f.ID.Eq(int64(id))).First()
	if err != nil {
		return nil, err
	}
	return toFileUploadBiz(m), nil
}

func (r *fileUploadRepo) FindByKey(ctx context.Context, key string) (*example.FileUpload, error) {
	f := query.ExaFileUploadAndDownload
	m, err := f.WithContext(ctx).Where(f.Key.Eq(key)).First()
	if err != nil {
		return nil, err
	}
	return toFileUploadBiz(m), nil
}

func (r *fileUploadRepo) List(ctx context.Context, req *example.FileUploadSearchReq) ([]*example.FileUpload, int64, error) {
	f := query.ExaFileUploadAndDownload
	q := f.WithContext(ctx)

	if req.Keyword != "" {
		q = q.Where(f.Name.Like("%" + req.Keyword + "%"))
	}
	if req.ClassId > 0 {
		q = q.Where(f.ClassID.Eq(int64(req.ClassId)))
	}

	total, err := q.Count()
	if err != nil {
		return nil, 0, err
	}

	offset := (req.Page - 1) * req.PageSize
	list, err := q.Order(f.ID.Desc()).Offset(offset).Limit(req.PageSize).Find()
	if err != nil {
		return nil, 0, err
	}

	result := make([]*example.FileUpload, len(list))
	for i, m := range list {
		result[i] = toFileUploadBiz(m)
	}
	return result, total, nil
}

func (r *fileUploadRepo) BatchCreate(ctx context.Context, files []*example.FileUpload) error {
	models := make([]*model.ExaFileUploadAndDownload, len(files))
	for i, f := range files {
		models[i] = toFileUploadModel(f)
	}
	return r.db.WithContext(ctx).Create(&models).Error
}

// 转换函数
func toFileUploadModel(f *example.FileUpload) *model.ExaFileUploadAndDownload {
	return &model.ExaFileUploadAndDownload{
		ID:      int64(f.ID),
		Name:    f.Name,
		ClassID: int64(f.ClassId),
		URL:     f.Url,
		Tag:     f.Tag,
		Key:     f.Key,
	}
}

func toFileUploadBiz(m *model.ExaFileUploadAndDownload) *example.FileUpload {
	return &example.FileUpload{
		ID:        uint(m.ID),
		Name:      m.Name,
		ClassId:   int(m.ClassID),
		Url:       m.URL,
		Tag:       m.Tag,
		Key:       m.Key,
		CreatedAt: m.CreatedAt,
		UpdatedAt: m.UpdatedAt,
	}
}
