package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	"linkmaster-node/internal/config"
	"linkmaster-node/internal/heartbeat"
	"linkmaster-node/internal/recovery"
	"linkmaster-node/internal/server"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var version = "1.1.0" // 编译时通过 -ldflags "-X main.version=xxx" 设置

func main() {
	// 加载配置
	cfg, err := config.Load()
	if err != nil {
		fmt.Printf("加载配置失败: %v\n", err)
		os.Exit(1)
	}

	// 初始化日志
	logger, err := initLogger(cfg)
	if err != nil {
		fmt.Printf("初始化日志失败: %v\n", err)
		os.Exit(1)
	}
	defer logger.Sync()

	logger.Info("节点服务启动", zap.String("version", version))

	// 初始化错误恢复
	recovery.Init()

	// 如果配置中没有节点信息，先发送一次心跳获取节点信息
	if cfg.Node.ID == 0 || cfg.Node.IP == "" {
		logger.Info("节点信息未配置，发送心跳获取节点信息")
		if err := heartbeat.RegisterNode(cfg); err != nil {
			logger.Warn("注册节点失败，将在心跳时重试", zap.Error(err))
		} else {
			logger.Info("节点信息已获取并保存",
				zap.Uint("node_id", cfg.Node.ID),
				zap.String("node_ip", cfg.Node.IP),
				zap.String("location", fmt.Sprintf("%s/%s/%s", cfg.Node.Country, cfg.Node.Province, cfg.Node.City)))
		}
	}

	// 启动心跳上报
	heartbeatReporter := heartbeat.NewReporter(cfg)
	go heartbeatReporter.Start(context.Background())

	// 启动HTTP服务器
	httpServer := server.NewHTTPServer(cfg)
	go func() {
		if err := httpServer.Start(); err != nil {
			logger.Fatal("HTTP服务器启动失败", zap.Error(err))
		}
	}()

	// 等待中断信号
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
	<-sigChan

	logger.Info("收到停止信号，正在关闭服务...")

	// 优雅关闭
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	httpServer.Shutdown(ctx)
	heartbeatReporter.Stop()

	logger.Info("服务已关闭")
}

func initLogger(cfg *config.Config) (*zap.Logger, error) {
	// 确定日志级别
	var level zapcore.Level
	logLevel := cfg.Log.Level
	if logLevel == "" {
		if cfg.Debug {
			logLevel = "debug"
		} else {
			logLevel = "info"
		}
	}

	switch logLevel {
	case "debug":
		level = zapcore.DebugLevel
	case "info":
		level = zapcore.InfoLevel
	case "warn":
		level = zapcore.WarnLevel
	case "error":
		level = zapcore.ErrorLevel
	default:
		level = zapcore.InfoLevel
	}

	// 编码器配置
	encoderConfig := zap.NewProductionEncoderConfig()
	if cfg.Debug {
		encoderConfig = zap.NewDevelopmentEncoderConfig()
	}
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder

	// 确定输出目标
	var writeSyncer zapcore.WriteSyncer
	if cfg.Log.File != "" {
		// 确保日志目录存在
		logDir := filepath.Dir(cfg.Log.File)
		if logDir != "." && logDir != "" {
			if err := os.MkdirAll(logDir, 0755); err != nil {
				return nil, fmt.Errorf("创建日志目录失败: %w", err)
			}
		}

		// 打开日志文件（追加模式）
		logFile, err := os.OpenFile(cfg.Log.File, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
		if err != nil {
			return nil, fmt.Errorf("打开日志文件失败: %w", err)
		}
		writeSyncer = zapcore.AddSync(logFile)
	} else {
		// 输出到标准错误（兼容原有行为）
		writeSyncer = zapcore.AddSync(os.Stderr)
	}

	// 创建核心
	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		writeSyncer,
		level,
	)

	// 创建 logger
	logger := zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))

	return logger, nil
}
