// Package generic provides a fallback parser for unrecognized text files
package generic

import (
	"strings"
	"time"

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

// parserVersion - version of this parser module
const parserVersion = "1.1"

func init() {
	parser.Register(&Parser{})
}

// Parser implements VendorParser for generic text files
type Parser struct{}

// Name returns human-readable parser name
func (p *Parser) Name() string {
	return "Generic Text File Parser"
}

// Vendor returns vendor identifier
func (p *Parser) Vendor() string {
	return "generic"
}

// Version returns parser version
func (p *Parser) Version() string {
	return parserVersion
}

// Detect checks if this is a text file (fallback with low confidence)
// Returns confidence 0-100
func (p *Parser) Detect(files []parser.ExtractedFile) int {
	// Only detect if there's exactly one file (plain .gz or single file)
	if len(files) != 1 {
		return 0
	}

	file := files[0]

	// Check if content looks like text (not binary)
	if !isLikelyText(file.Content) {
		return 0
	}

	// Return low confidence so other parsers have priority
	return 15
}

// isLikelyText checks if content is likely text (not binary)
func isLikelyText(content []byte) bool {
	// Check first 512 bytes for binary data
	sample := content
	if len(content) > 512 {
		sample = content[:512]
	}

	binaryCount := 0
	for _, b := range sample {
		// Count non-printable characters (excluding common whitespace)
		if b < 32 && b != '\n' && b != '\r' && b != '\t' {
			binaryCount++
		}
		if b == 0 { // NULL byte is a strong indicator of binary
			binaryCount += 10
		}
	}

	// If less than 5% binary, consider it text
	return binaryCount < len(sample)/20
}

// Parse parses generic text file
func (p *Parser) Parse(files []parser.ExtractedFile) (*models.AnalysisResult, error) {
	result := &models.AnalysisResult{
		Events:  make([]models.Event, 0),
		FRU:     make([]models.FRUInfo, 0),
		Sensors: make([]models.SensorReading, 0),
	}

	// Initialize hardware config
	result.Hardware = &models.HardwareConfig{}

	if len(files) == 0 {
		return result, nil
	}

	file := files[0]
	content := string(file.Content)

	// Create a single event with file info
	result.Events = append(result.Events, models.Event{
		Timestamp:   time.Now(),
		Source:      "File",
		EventType:   "Text File",
		Description: "Generic text file loaded",
		Severity:    models.SeverityInfo,
		RawData:     "Filename: " + file.Path,
	})

	// Try to extract some basic info from common file types
	if strings.Contains(strings.ToLower(file.Path), "nvidia-bug-report") {
		parseNvidiaBugReport(content, result)
	}

	return result, nil
}

// parseNvidiaBugReport extracts info from nvidia-bug-report files
func parseNvidiaBugReport(content string, result *models.AnalysisResult) {
	lines := strings.Split(content, "\n")

	// Look for GPU information
	for i, line := range lines {
		// Find NVIDIA driver version
		if strings.Contains(line, "NVRM version:") || strings.Contains(line, "nvidia-smi") {
			if i+5 < len(lines) {
				result.Events = append(result.Events, models.Event{
					Timestamp:   time.Now(),
					Source:      "NVIDIA Driver",
					EventType:   "Driver Info",
					Description: "NVIDIA driver information found",
					Severity:    models.SeverityInfo,
					RawData:     strings.TrimSpace(line),
				})
			}
		}

		// Find GPU devices
		if strings.Contains(line, "/proc/driver/nvidia/gpus/") && strings.Contains(line, "***") {
			result.Events = append(result.Events, models.Event{
				Timestamp:   time.Now(),
				Source:      "GPU",
				EventType:   "GPU Device",
				Description: "GPU device detected",
				Severity:    models.SeverityInfo,
				RawData:     strings.TrimSpace(line),
			})
		}
	}
}
