package main

import (
	"log"

	"metazone.cc/metalab/internal/common"
	"metazone.cc/metalab/internal/config"
	"metazone.cc/metalab/internal/model"
	"metazone.cc/metalab/internal/router"
	"metazone.cc/metalab/internal/theme"

	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

func main() {
	// 配置
	cfg := config.Load("config.yaml")

	// 从配置初始化角色系统（OCP：新增角色无需修改源代码）
	model.InitRoles(cfg.Roles.Levels, cfg.Roles.Names, cfg.Roles.Permissions.OperableRoles)

	// 数据库
	db, err := gorm.Open(postgres.Open(cfg.Database.DSN()), &gorm.Config{})
	if err != nil {
		log.Fatalf("连接数据库失败: %v", err)
	}
	if err := db.AutoMigrate(&model.User{}, &model.AuditSubmission{}, &model.SiteSetting{}, &model.Notification{}, &model.Post{}); err != nil {
		log.Fatalf("数据库迁移失败: %v", err)
	}

	// 邮箱唯一索引迁移：从全表唯一改为部分唯一（仅 deleted_at IS NULL 的行）
	// 支持软删除用户邮箱复用
	migrations := []string{
		`DROP INDEX IF EXISTS idx_users_email`,
		`CREATE INDEX IF NOT EXISTS idx_users_email ON users (email)`,
		`CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email_active ON users (email) WHERE deleted_at IS NULL`,
	}
	for _, m := range migrations {
		if err := db.Exec(m).Error; err != nil {
			log.Fatalf("数据库迁移失败 (%s): %v", m, err)
		}
	}
	log.Println("数据库连接成功")

	// Gin 模式
	gin.SetMode(cfg.Server.Mode)

	r := gin.Default()

	// 计算静态资源哈希（用于缓存破坏，文件不变哈希不变）
	common.ComputeAssetHashes("templates/MetaLab-2026")

	// 模板加载（前端主题 + 管理后台）
	tmpl, err := theme.LoadTemplates(
		theme.TemplateRoot{Dir: "templates/MetaLab-2026/html", Prefix: ""},
		theme.TemplateRoot{Dir: "templates/admin/html", Prefix: "admin/"},
	)
	if err != nil {
		panic("加载模板失败: " + err.Error())
	}
	r.SetHTMLTemplate(tmpl)

	// 静态资源
	r.Static("/static", "./templates/MetaLab-2026/static")
	r.Static("/admin/static", "./templates/admin/static")
	r.Static("/shared/static", "./templates/shared/static")
	r.Static("/uploads/avatars", "./storage/uploads/avatars")
	r.Static("/uploads/posts", "./storage/uploads/posts")

	// Redis 客户端（可选，不可达时 FallbackStore 自动降级，恢复后自动切回）
	var redisClient *redis.Client
	if cfg.Redis.Enabled {
		redisClient, err = common.NewRedisClient(cfg.Redis)
		if err != nil {
			log.Printf("Redis 不可达，启动后首次请求将自动降级，后续恢复自动切回: %v", err)
			// 不置 nil：go-redis 自带重连，FallbackStore 负责健康检测与恢复
		} else {
			log.Printf("Redis 已连接 %s:%s (DB=%d)", cfg.Redis.Host, cfg.Redis.Port, cfg.Redis.DB)
		}
	} else {
		log.Println("Redis 未启用，使用内存存储")
	}

	// 站点设置管理器（DB 持久化 + 内存缓存）
	siteSettings, err := config.NewSiteSettings(db)
	if err != nil {
		log.Fatalf("初始化站点设置失败: %v", err)
	}

	// 路由注册
	router.Setup(r, db, cfg, siteSettings, redisClient)

	// 启动
	log.Printf("MetaZone.FAN 启动于 0.0.0.0:%s", cfg.Server.Port)
	r.Run("0.0.0.0:" + cfg.Server.Port)
}
