package biz

import (
	"context"
	"errors"
	"time"
)

var (
	ErrInvalidLogMonth    = errors.New("日志月份格式不正确")
	ErrInvalidLogDate     = errors.New("日志日期格式不正确")
	ErrInvalidLogPath     = errors.New("日志文件路径不合法")
	ErrLogFileNotFound    = errors.New("日志文件不存在")
	ErrLogFileUnreadable  = errors.New("日志文件不可读取")
	ErrLogRootUnavailable = errors.New("日志目录不可读取")
)

type OperationRecord struct {
	ID                                  uint
	CreatedAt                           time.Time
	UpdatedAt                           time.Time
	IP, Method, Path                    string
	Status                              int
	LatencyMS                           int64
	Agent, ErrorMessage, Body, Response string
	UserID                              uint
	RequestID, TraceID, DeviceID        string
	User                                *User
}

type LoginLog struct {
	ID                  uint
	CreatedAt           time.Time
	UpdatedAt           time.Time
	Username, IP        string
	Status              bool
	ErrorMessage, Agent string
	UserID              uint
	User                *User
	FilterByStatus      bool
}

type DataAccessLog struct {
	ID                                uint
	CreatedAt                         time.Time
	UpdatedAt                         time.Time
	EventType, TargetTable, Operation string
	UserID, AuthorityID               uint
	Scope                             int
	RequestID, Method, Path, Detail   string
}

type LogDate struct {
	Date      string
	FileCount int
}
type LogFile struct {
	Path, Name string
	Size       int64
	ModifiedAt time.Time
}
type LogContent struct {
	Date, Path, Content     string
	LineCount               int
	NextCursor              int64
	HasMore, LimitedByBytes bool
	Size                    int64
	ModifiedAt              time.Time
}

type LogFileRepo interface {
	LogDates(context.Context, string) ([]LogDate, error)
	LogFiles(context.Context, string) ([]LogFile, error)
	LogContent(context.Context, string, string, *int64) (*LogContent, error)
}

type LogViewerUsecase struct{ LogFileRepo }

func NewLogViewerUsecase(repo LogFileRepo) *LogViewerUsecase {
	return &LogViewerUsecase{LogFileRepo: repo}
}

type ErrorRecord struct {
	ID                   uint
	CreatedAt, UpdatedAt time.Time
	Form, Info, Solution *string
	Level                string
	RequestID, TraceID   string
	Status               string
	CreatedAtRange       []time.Time
}

type AuditRecordRepo interface {
	RecordOperation(context.Context, *OperationRecord) error
	RecordLogin(context.Context, *LoginLog) error
	RecordDataAccess(context.Context, *DataAccessLog) error
	CreateError(context.Context, *ErrorRecord) error
}

type AuditQueryRepo interface {
	ListOperations(context.Context, int, int, *OperationRecord) ([]*OperationRecord, int64, error)
	FindOperation(context.Context, uint) (*OperationRecord, error)
	DeleteOperations(context.Context, []int) error
	ListLogins(context.Context, int, int, *LoginLog) ([]*LoginLog, int64, error)
	FindLogin(context.Context, uint) (*LoginLog, error)
	DeleteLogins(context.Context, []int) error
	ListDataAccess(context.Context, int, int, *DataAccessLog) ([]*DataAccessLog, int64, error)
	DeleteDataAccess(context.Context, []uint) error
	UpdateError(context.Context, *ErrorRecord) error
	DeleteErrors(context.Context, []uint) error
	FindError(context.Context, uint) (*ErrorRecord, error)
	ListErrors(context.Context, int, int, *ErrorRecord) ([]*ErrorRecord, int64, error)
}

type AuditUsecase struct{ AuditQueryRepo }

func NewAuditUsecase(repo AuditQueryRepo) *AuditUsecase {
	return &AuditUsecase{AuditQueryRepo: repo}
}

type AuditRecorderUsecase struct{ AuditRecordRepo }

func NewAuditRecorderUsecase(repo AuditRecordRepo) *AuditRecorderUsecase {
	return &AuditRecorderUsecase{AuditRecordRepo: repo}
}
