package audit

import (
	"bytes"
	"encoding/csv"
	"fmt"
	"time"

	"hyapp-admin-server/internal/model"
	"hyapp-admin-server/internal/modules/shared"
	"hyapp-admin-server/internal/repository"
)

type AuditService struct {
	store *repository.Store
}

type CSVExport struct {
	FileName string
	Content  []byte
	Count    int
}

func NewService(store *repository.Store) *AuditService {
	return &AuditService{store: store}
}

func (s *AuditService) CreateOperationLog(log model.OperationLog) error {
	return s.store.CreateOperationLog(log)
}

func (s *AuditService) LogOperation(event shared.OperationEvent) error {
	if event.Status == "" {
		event.Status = "success"
	}
	if event.RiskLevel == "" {
		event.RiskLevel = riskLevel(event.Action, event.Method)
	}
	return s.store.CreateOperationLog(model.OperationLog{
		RequestID:  event.RequestID,
		UserID:     event.UserID,
		Username:   event.Username,
		Action:     event.Action,
		Resource:   event.Resource,
		ResourceID: event.ResourceID,
		Method:     event.Method,
		Path:       event.Path,
		IP:         event.IP,
		UserAgent:  event.UserAgent,
		Status:     event.Status,
		HTTPStatus: event.HTTPStatus,
		RiskLevel:  event.RiskLevel,
		LatencyMS:  event.LatencyMS,
		Detail:     event.Detail,
	})
}

func (s *AuditService) ListLoginLogs(options repository.ListOptions) ([]model.LoginLog, int64, error) {
	return s.store.ListLoginLogs(options)
}

func (s *AuditService) ListOperationLogs(options repository.ListOptions) ([]model.OperationLog, int64, error) {
	return s.store.ListOperationLogs(options)
}

func (s *AuditService) ExportLoginLogs(options repository.ListOptions) (CSVExport, error) {
	logs, err := s.store.ExportLoginLogs(options)
	if err != nil {
		return CSVExport{}, err
	}
	var buf bytes.Buffer
	writer := csv.NewWriter(&buf)
	_ = writer.Write([]string{"ID", "用户", "IP", "状态", "消息", "时间"})
	for _, item := range logs {
		_ = writer.Write([]string{
			fmt.Sprintf("%d", item.ID),
			item.Username,
			item.IP,
			item.Status,
			item.Message,
			time.UnixMilli(item.CreatedAtMS).UTC().Format(time.RFC3339),
		})
	}
	writer.Flush()
	return CSVExport{FileName: "hyapp-login-logs.csv", Content: buf.Bytes(), Count: len(logs)}, writer.Error()
}

func (s *AuditService) ExportOperationLogs(options repository.ListOptions) (CSVExport, error) {
	logs, err := s.store.ExportOperationLogs(options)
	if err != nil {
		return CSVExport{}, err
	}
	var buf bytes.Buffer
	writer := csv.NewWriter(&buf)
	_ = writer.Write([]string{"ID", "RequestID", "用户", "动作", "资源", "资源ID", "方法", "路径", "IP", "状态", "HTTP", "风险", "耗时ms", "详情", "时间"})
	for _, item := range logs {
		_ = writer.Write([]string{
			fmt.Sprintf("%d", item.ID),
			item.RequestID,
			item.Username,
			item.Action,
			item.Resource,
			item.ResourceID,
			item.Method,
			item.Path,
			item.IP,
			item.Status,
			fmt.Sprintf("%d", item.HTTPStatus),
			item.RiskLevel,
			fmt.Sprintf("%d", item.LatencyMS),
			item.Detail,
			time.UnixMilli(item.CreatedAtMS).UTC().Format(time.RFC3339),
		})
	}
	writer.Flush()
	return CSVExport{FileName: "hyapp-operation-logs.csv", Content: buf.Bytes(), Count: len(logs)}, writer.Error()
}

func riskLevel(action string, method string) string {
	switch method {
	case "DELETE":
		return "high"
	case "POST", "PUT", "PATCH":
		if action == "reset-user-password" || action == "replace-role-permissions" || action == "replace-role-data-scopes" {
			return "high"
		}
		return "normal"
	default:
		return "low"
	}
}
