package inspection

import (
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"dc-inspection/internal/config"
	esclient "dc-inspection/pkg/elasticsearch"
)

// ESLogInspector ELK 异常日志检索巡检器
type ESLogInspector struct {
	cfg    *config.ESConfig
	client *esclient.Client
}

// NewESLogInspector 创建 ES 日志巡检器
func NewESLogInspector(cfg *config.ESConfig) *ESLogInspector {
	return &ESLogInspector{
		cfg:    cfg,
		client: esclient.NewClient(cfg.Hosts, cfg.Username, cfg.Password),
	}
}

// ESLogReport ES 日志巡检报告
type ESLogReport struct {
	Index         string             `json:"index"`
	TimeRange     string             `json:"time_range"`
	MinLevel      string             `json:"min_level"`
	TotalAbnormal int                `json:"total_abnormal"`
	ErrorCount    int                `json:"error_count"`
	FatalCount    int                `json:"fatal_count"`
	WarnCount     int                `json:"warn_count"`
	TopErrors     []esclient.LogEntry `json:"top_errors"`
	Errors        []string           `json:"errors,omitempty"`
	ScannedAt     time.Time          `json:"scanned_at"`
}

// Inspect 执行 ES 异常日志检索
func (e *ESLogInspector) Inspect() *ESLogReport {
	report := &ESLogReport{
		Index:     e.cfg.Index,
		TimeRange: e.cfg.TimeRange,
		MinLevel:  e.cfg.MinLevel,
		ScannedAt: time.Now(),
	}

	// 检测 ES 连通性
	if err := e.client.Ping(); err != nil {
		report.Errors = append(report.Errors, fmt.Sprintf("ES 连接失败: %v", err))
		return report
	}

	// 检索异常日志
	result, err := e.client.SearchAbnormalLogs(e.cfg.Index, e.cfg.TimeRange, e.cfg.MinLevel)
	if err != nil {
		report.Errors = append(report.Errors, fmt.Sprintf("ES 检索失败: %v", err))
		return report
	}

	report.TotalAbnormal = result.Total
	report.TopErrors = result.Logs

	// 统计各级别日志数量
	for _, log := range result.Logs {
		switch strings.ToUpper(log.Level) {
		case "ERROR":
			report.ErrorCount++
		case "FATAL":
			report.FatalCount++
		case "WARN", "WARNING":
			report.WarnCount++
		}
	}

	return report
}

// CheckThresholds 检查 ES 日志异常阈值
func (e *ESLogInspector) CheckThresholds(report *ESLogReport) []string {
	var alerts []string

	if len(report.Errors) > 0 {
		alerts = append(alerts, fmt.Sprintf("ES 日志检索异常: %s", strings.Join(report.Errors, "; ")))
		return alerts
	}

	// FATAL 级别日志告警
	if report.FatalCount > 0 {
		alerts = append(alerts, fmt.Sprintf("ELK 检测到 %d 条 FATAL 级别日志", report.FatalCount))
	}

	// ERROR 级别日志过多告警
	if report.ErrorCount > 50 {
		alerts = append(alerts, fmt.Sprintf("ELK 检测到 %d 条 ERROR 级别日志，数量异常", report.ErrorCount))
	}

	// 总异常日志告警
	if report.TotalAbnormal > 100 {
		alerts = append(alerts, fmt.Sprintf("ELK 近 %s 内异常日志总数 %d，超过阈值 100",
			report.TimeRange, report.TotalAbnormal))
	}

	return alerts
}

// ToRecord 将巡检结果转换为数据库记录
func (e *ESLogInspector) ToRecord(report *ESLogReport) *Record {
	status := "ok"
	alerts := e.CheckThresholds(report)

	if len(report.Errors) > 0 {
		status = "error"
	} else if report.FatalCount > 0 {
		status = "critical"
	} else if len(alerts) > 0 {
		status = "warning"
	}

	metricsJSON, _ := json.Marshal(report)

	// 构建详情摘要
	var detailBuilder strings.Builder
	detailBuilder.WriteString(fmt.Sprintf("异常日志总数: %d (FATAL:%d ERROR:%d WARN:%d)\n",
		report.TotalAbnormal, report.FatalCount, report.ErrorCount, report.WarnCount))

	// 列出前 5 条错误日志
	maxShow := 5
	if len(report.TopErrors) < maxShow {
		maxShow = len(report.TopErrors)
	}
	for i := 0; i < maxShow; i++ {
		log := report.TopErrors[i]
		detailBuilder.WriteString(fmt.Sprintf("  [%s] %s: %s\n", log.Timestamp, log.Level, log.Message))
	}

	return &Record{
		InspectionType: "es_log",
		Target:         report.Index,
		Status:         status,
		Metrics:        string(metricsJSON),
		Details:        detailBuilder.String(),
		Message:        strings.Join(alerts, "\n"),
		InspectedAt:    time.Now(),
	}
}
