package system

import (
	"context"

	"kra/internal/biz/system"
	"kra/internal/data/model"

	"gorm.io/gorm"
)

type operationRecordRepo struct {
	db *gorm.DB
}

// NewOperationRecordRepo 创建操作记录仓储
func NewOperationRecordRepo(db *gorm.DB) system.OperationRecordRepo {
	return &operationRecordRepo{db: db}
}

func (r *operationRecordRepo) Create(ctx context.Context, record *system.OperationRecord) error {
	m := toModelOperationRecord(record)
	if err := r.db.WithContext(ctx).Create(m).Error; err != nil {
		return err
	}
	record.ID = uint(m.ID)
	return nil
}

func (r *operationRecordRepo) Delete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Delete(&model.SysOperationRecord{}, id).Error
}

func (r *operationRecordRepo) DeleteByIds(ctx context.Context, ids []uint) error {
	return r.db.WithContext(ctx).Delete(&model.SysOperationRecord{}, "id in (?)", ids).Error
}

func (r *operationRecordRepo) FindByID(ctx context.Context, id uint) (*system.OperationRecord, error) {
	var m model.SysOperationRecord
	if err := r.db.WithContext(ctx).Where("id = ?", id).First(&m).Error; err != nil {
		return nil, err
	}
	return toBizOperationRecord(&m, nil), nil
}

func (r *operationRecordRepo) List(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*system.OperationRecord, int64, error) {
	db := r.db.WithContext(ctx).Model(&model.SysOperationRecord{})

	if v, ok := filters["method"]; ok && v != "" {
		db = db.Where("method = ?", v)
	}
	if v, ok := filters["path"]; ok && v != "" {
		db = db.Where("path LIKE ?", "%"+v.(string)+"%")
	}
	if v, ok := filters["status"]; ok && v.(int) != 0 {
		db = db.Where("status = ?", v)
	}

	var total int64
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	offset := (page - 1) * pageSize
	var list []model.SysOperationRecord
	if err := db.Order("id desc").Offset(offset).Limit(pageSize).Find(&list).Error; err != nil {
		return nil, 0, err
	}

	// 预加载用户信息
	userIDs := make([]int64, 0)
	for _, m := range list {
		userIDs = append(userIDs, m.UserID)
	}
	userMap := make(map[int64]*model.SysUser)
	if len(userIDs) > 0 {
		var users []model.SysUser
		r.db.WithContext(ctx).Where("id in (?)", userIDs).Find(&users)
		for i := range users {
			userMap[users[i].ID] = &users[i]
		}
	}

	result := make([]*system.OperationRecord, len(list))
	for i, m := range list {
		user := userMap[m.UserID]
		result[i] = toBizOperationRecord(&m, user)
	}
	return result, total, nil
}

// 转换函数
func toModelOperationRecord(r *system.OperationRecord) *model.SysOperationRecord {
	return &model.SysOperationRecord{
		ID:           int64(r.ID),
		IP:           r.IP,
		Method:       r.Method,
		Path:         r.Path,
		Status:       int64(r.Status),
		Latency:      r.Latency,
		Agent:        r.Agent,
		ErrorMessage: r.ErrorMessage,
		Body:         r.Body,
		Resp:         r.Resp,
		UserID:       int64(r.UserID),
	}
}

func toBizOperationRecord(m *model.SysOperationRecord, user *model.SysUser) *system.OperationRecord {
	r := &system.OperationRecord{
		ID:           uint(m.ID),
		IP:           m.IP,
		Method:       m.Method,
		Path:         m.Path,
		Status:       int(m.Status),
		Latency:      m.Latency,
		Agent:        m.Agent,
		ErrorMessage: m.ErrorMessage,
		Body:         m.Body,
		Resp:         m.Resp,
		UserID:       uint(m.UserID),
	}
	if user != nil {
		r.User = &system.User{
			ID:       uint(user.ID),
			Username: user.Username,
			NickName: user.NickName,
		}
	}
	return r
}
