package inspur

import (
	"bufio"
	"regexp"
	"strings"
	"time"

	"git.mchus.pro/mchus/logpile/internal/models"
)

var (
	// Syslog format: <priority> timestamp hostname process: message
	syslogRegex = regexp.MustCompile(`^<(\d+)>\s*(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[^\s]*)\s+(\S+)\s+(\S+):\s*(.*)$`)
)

// ParseSyslog parses syslog format logs
func ParseSyslog(content []byte, sourcePath string) []models.Event {
	var events []models.Event

	// Determine severity from file path
	severity := determineSeverityFromPath(sourcePath)

	scanner := bufio.NewScanner(strings.NewReader(string(content)))
	lineNum := 0

	for scanner.Scan() {
		lineNum++
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}

		matches := syslogRegex.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		timestamp, err := time.Parse(time.RFC3339, matches[2])
		if err != nil {
			// Try alternative format
			timestamp, err = time.Parse("2006-01-02T15:04:05.000000-07:00", matches[2])
			if err != nil {
				continue
			}
		}

		event := models.Event{
			ID:          generateEventID(sourcePath, lineNum),
			Timestamp:   timestamp,
			Source:      "syslog",
			SensorType:  "syslog",
			SensorName:  matches[4],
			Description: matches[5],
			Severity:    severity,
			RawData:     line,
		}

		events = append(events, event)
	}

	return events
}

func determineSeverityFromPath(path string) models.Severity {
	pathLower := strings.ToLower(path)

	switch {
	case strings.Contains(pathLower, "emerg") || strings.Contains(pathLower, "alert") ||
		strings.Contains(pathLower, "crit"):
		return models.SeverityCritical
	case strings.Contains(pathLower, "warn") || strings.Contains(pathLower, "error"):
		return models.SeverityWarning
	default:
		return models.SeverityInfo
	}
}

func generateEventID(source string, lineNum int) string {
	parts := strings.Split(source, "/")
	filename := parts[len(parts)-1]
	return strings.TrimSuffix(filename, ".log") + "_" + itoa(lineNum)
}

func itoa(i int) string {
	if i == 0 {
		return "0"
	}
	var b [20]byte
	pos := len(b)
	for i > 0 {
		pos--
		b[pos] = byte('0' + i%10)
		i /= 10
	}
	return string(b[pos:])
}
