package system

import (
	"context"
	"strconv"

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

	"gorm.io/gorm"
)

type errorRepo struct {
	db *gorm.DB
}

// NewErrorRepo 创建错误日志仓储
func NewErrorRepo(db *gorm.DB) system.ErrorRepo {
	return &errorRepo{db: db}
}

func (r *errorRepo) Create(ctx context.Context, sysError *system.SysError) error {
	m := toModelError(sysError)
	return query.SysError.WithContext(ctx).Create(m)
}

func (r *errorRepo) Delete(ctx context.Context, id string) error {
	_, err := query.SysError.WithContext(ctx).Where(query.SysError.ID.Eq(parseID(id))).Delete()
	return err
}

func (r *errorRepo) DeleteByIds(ctx context.Context, ids []string) error {
	idList := make([]int64, len(ids))
	for i, id := range ids {
		idList[i] = parseID(id)
	}
	_, err := query.SysError.WithContext(ctx).Where(query.SysError.ID.In(idList...)).Delete()
	return err
}

func (r *errorRepo) Update(ctx context.Context, sysError *system.SysError) error {
	_, err := query.SysError.WithContext(ctx).Where(query.SysError.ID.Eq(sysError.ID)).Updates(map[string]any{
		"form":     sysError.Form,
		"info":     sysError.Info,
		"level":    sysError.Level,
		"solution": sysError.Solution,
		"status":   sysError.Status,
	})
	return err
}

func (r *errorRepo) GetById(ctx context.Context, id string) (*system.SysError, error) {
	m, err := query.SysError.WithContext(ctx).Where(query.SysError.ID.Eq(parseID(id))).First()
	if err != nil {
		return nil, err
	}
	return toBizError(m), nil
}

func (r *errorRepo) GetList(ctx context.Context, req *system.ErrorSearchReq) ([]*system.SysError, int64, error) {
	q := query.SysError.WithContext(ctx).Order(query.SysError.CreatedAt.Desc())

	// 条件搜索
	if len(req.CreatedAtRange) == 2 {
		q = q.Where(query.SysError.CreatedAt.Between(req.CreatedAtRange[0], req.CreatedAtRange[1]))
	}
	if req.Form != nil && *req.Form != "" {
		q = q.Where(query.SysError.Form.Eq(*req.Form))
	}
	if req.Info != nil && *req.Info != "" {
		q = q.Where(query.SysError.Info.Like("%" + *req.Info + "%"))
	}

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

	if req.PageSize > 0 {
		offset := req.PageSize * (req.Page - 1)
		q = q.Limit(req.PageSize).Offset(offset)
	}

	list, err := q.Find()
	if err != nil {
		return nil, 0, err
	}

	result := make([]*system.SysError, len(list))
	for i, m := range list {
		result[i] = toBizError(m)
	}
	return result, total, nil
}

func (r *errorRepo) UpdateStatus(ctx context.Context, id string, status string) error {
	_, err := query.SysError.WithContext(ctx).Where(query.SysError.ID.Eq(parseID(id))).Update(query.SysError.Status, status)
	return err
}

func (r *errorRepo) UpdateSolution(ctx context.Context, id string, status string, solution string) error {
	_, err := query.SysError.WithContext(ctx).Where(query.SysError.ID.Eq(parseID(id))).Updates(map[string]any{
		"status":   status,
		"solution": solution,
	})
	return err
}

// 转换函数
func parseID(id string) int64 {
	n, _ := strconv.ParseInt(id, 10, 64)
	return n
}

func toModelError(e *system.SysError) *model.SysError {
	return &model.SysError{
		ID:       e.ID,
		Form:     e.Form,
		Info:     e.Info,
		Level:    e.Level,
		Solution: e.Solution,
		Status:   e.Status,
	}
}

func toBizError(m *model.SysError) *system.SysError {
	return &system.SysError{
		ID:        m.ID,
		Form:      m.Form,
		Info:      m.Info,
		Level:     m.Level,
		Solution:  m.Solution,
		Status:    m.Status,
		CreatedAt: m.CreatedAt,
		UpdatedAt: m.UpdatedAt,
	}
}
