package monitor

import (
	"fmt"
	"log"
	"regexp"
	"strings"
	"time"

	"github.com/coreos/go-systemd/sdjournal"
	"github.com/wuko233/sysmonitord/internal/config"
)

func NewSSHMonitor(cfg *config.SSHMonitor, alertChan chan<- Alert) *SSHMonitor {
	return &SSHMonitor{
		config:    cfg,
		alertChan: alertChan,
		stopChan:  make(chan struct{}),
	}
}

func (m *SSHMonitor) Start() error {
	log.Println("启动SSH监控...")
	return m.startJournalMonitor()
}

func (m *SSHMonitor) Stop() error {
	log.Println("停止SSH监控...")
	close(m.stopChan)
	if m.journal != nil {
		m.journal.Close()
	}
	return nil
}

func (m *SSHMonitor) startJournalMonitor() error {
	journal, err := sdjournal.NewJournal()
	if err != nil {
		return fmt.Errorf("打开日志失败: %v", err)
	}
	m.journal = journal

	filters := []string{
		"_TRANSPORT=syslog",
		"SYSLOG_IDENTIFIER=sshd",
	}

	for _, filter := range filters {
		if err := journal.AddMatch(filter); err != nil {
			return fmt.Errorf("添加日志过滤器%s失败: %v", filter, err)
		}
	}

	if err := journal.SeekTail(); err != nil {
		return fmt.Errorf("跳转到日志末尾失败: %v", err)
	}

	m.monitorJournal()

	return nil
}

func (m *SSHMonitor) monitorJournal() {
	for {
		select {
		case <-m.stopChan:
			return

		default:
			count, err := m.journal.Next()
			if err != nil {
				log.Printf("读取日志错误: %v", err)
				time.Sleep(time.Second)
				continue
			}
			if count == 0 {
				time.Sleep(100 * time.Millisecond)
				continue
			}

			entry, err := m.journal.GetEntry()
			if err != nil {
				log.Printf("获取日志条目错误: %v", err)
				continue
			}

			m.processLogEntry(entry.Fields)
		}
	}
}

func (m *SSHMonitor) processLogEntry(field map[string]string) {
	message, exists := field[sdjournal.SD_JOURNAL_FIELD_MESSAGE]

	if !exists {
		return
	}

	if strings.Contains(message, "Accepted") ||
		strings.Contains(message, "authentication failure") ||
		strings.Contains(message, "Failed password") {
		event := m.parseSSHEvent(field, message)
		if event != nil {
			m.handleSSHEvent(event)
		}
	}
}

func (m *SSHMonitor) parseSSHEvent(field map[string]string, message string) *SSHLoginEvent {
	var event *SSHLoginEvent

	if strings.Contains(message, "Accepted") {
		re := regexp.MustCompile(`Accepted (\S+) for (\S+) from ([\d\.:a-fA-F]+) port (\d+)`)
		// \S+ 匹配非空白字符，[\d\.:a-fA-F]+ 匹配IP地址
		matches := re.FindStringSubmatch(message)
		if matches != nil {
			// timestamp := time.Unix(0, int64(field[sdjournal.SD_JOURNAL_FIELD_REALTIME_TIMESTAMP])*int64(time.Microsecond))
			timestamp := time.Now()
			event = &SSHLoginEvent{
				Timestamp: timestamp,
				Hostname:  field["_HOSTNAME"],
				Username:  matches[2],
				Method:    matches[1],
				SourceIP:  matches[3],
				Port:      matches[4],
				Service:   field["SYSLOG_IDENTIFIER"],
				PID:       field["_PID"],
				Message:   message,
			}
		}

	}

	// Todo：处理其他情况

	return event
}

func (m *SSHMonitor) handleSSHEvent(event *SSHLoginEvent) {
	if m.config.DisplayOnShell {
		// 在终端显示事件
		m.displayEventOnShell(event)
	}

	if event.Username == "root" && m.config.AlertOnRootLogin {
		alert := Alert{
			Type:      "SSH_ROOT_LOGIN",
			Level:     "HIGH",
			Message:   fmt.Sprintf("检测到来自%s的root登录", event.SourceIP),
			Timestamp: time.Now(),
			Data:      event,
		}
		m.alertChan <- alert
	}

	log.Printf("SSH登录事件: 用户=%s, 来源IP=%s, 方式=%s",
		event.Username, event.SourceIP, event.Method)
}

func (m *SSHMonitor) displayEventOnShell(event *SSHLoginEvent) {
	fmt.Println("════════ SSH登录事件 ════════")
	fmt.Printf("时间: %s\n", event.Timestamp.Format("2006-01-02 15:04:05"))

	fmt.Printf("主机: %s\n", event.Hostname)
	fmt.Printf("用户: %s\n", event.Username)
	fmt.Printf("方式: %s\n", event.Method)
	fmt.Printf("来源IP: %s\n", event.SourceIP)
	fmt.Printf("端口: %s\n", event.Port)
	fmt.Printf("服务: %s (PID: %s)\n", event.Service, event.PID)
	fmt.Printf("消息: %s\n", event.Message)
	fmt.Println("════════════════════════════════")
}
