package services

import (
	"os"
	"path/filepath"

	"github.com/engigu/taskpool/internal/constant"
	"github.com/engigu/taskpool/internal/database"
	"github.com/engigu/taskpool/internal/logger"
	"github.com/engigu/taskpool/internal/utils"

	"gopkg.in/ini.v1"
)

// InstallRequest 安装请求
type InstallRequest struct {
	// 数据库配置
	DBType     string `json:"db_type" binding:"required"`     // sqlite 或 mysql
	DBHost     string `json:"db_host"`                        // MySQL 主机
	DBPort     int    `json:"db_port"`                        // MySQL 端口
	DBUser     string `json:"db_user"`                        // MySQL 用户名
	DBPassword string `json:"db_password"`                   // MySQL 密码
	DBName     string `json:"db_name"`                        // MySQL 数据库名
	DBPath     string `json:"db_path"`                        // SQLite 数据库路径
	DBSSLMode  string `json:"db_ssl_mode"`                   // SSL 模式

	// Redis 配置（可选）
	RedisEnabled bool   `json:"redis_enabled"`   // 是否启用 Redis
	RedisHost    string `json:"redis_host"`      // Redis 主机
	RedisPort    int    `json:"redis_port"`      // Redis 端口
	RedisPassword string `json:"redis_password"` // Redis 密码
	RedisDB      int    `json:"redis_db"`        // Redis 数据库索引

	// 管理员账号
	AdminUsername string `json:"admin_username" binding:"required"` // 管理员用户名
	AdminPassword string `json:"admin_password" binding:"required"` // 管理员密码
	AdminEmail    string `json:"admin_email"`                      // 管理员邮箱

	// 站点设置
	SiteTitle    string `json:"site_title"`    // 站点标题
	SiteSubtitle string `json:"site_subtitle"` // 站点副标题
}

// InstallStatus 安装状态
type InstallStatus struct {
	Installed   bool   `json:"installed"`
	ConfigPath  string `json:"config_path"`
	DBType      string `json:"db_type"`
}

// InstallService 安装服务
type InstallService struct {
	settingsService *SettingsService
	userService     *UserService
}

// NewInstallService 创建安装服务
func NewInstallService() *InstallService {
	return &InstallService{
		settingsService: NewSettingsService(),
		userService:     NewUserService(),
	}
}

// CheckInstallStatus 检查安装状态
func (s *InstallService) CheckInstallStatus() (*InstallStatus, error) {
	status := &InstallStatus{
		ConfigPath: constant.ConfigPath,
	}

	// 检查配置文件是否存在
	configExists := false
	if _, err := os.Stat(constant.ConfigPath); err == nil {
		configExists = true
	}

	// 检查是否已初始化（数据库中有管理员用户）
	initialized := false
	if configExists {
		// 尝试检查是否有管理员用户
		admin := s.userService.GetUserByUsername("admin")
		if admin != nil {
			initialized = true
		}
	}

	// 同时检查数据库中的初始化标志
	dbInitialized := s.settingsService.Get(constant.SectionSystem, constant.KeyInitialized)
	if dbInitialized == "true" {
		initialized = true
	}

	status.Installed = initialized
	status.DBType = Config.Database.Type

	return status, nil
}

// Install 执行安装
func (s *InstallService) Install(req *InstallRequest) error {
	// 1. 创建配置文件
	if err := s.createConfigFile(req); err != nil {
		return err
	}

	// 2. 重新加载数据库配置
	if err := s.reloadDatabase(req); err != nil {
		return err
	}

	// 3. 初始化数据库
	if err := database.Migrate(); err != nil {
		return err
	}

	// 4. 初始化设置
	if err := s.settingsService.InitSettings(); err != nil {
		logger.Warnf("[Install] 初始化设置失败: %v", err)
	}

	// 5. 创建管理员账号
	if err := s.createAdmin(req); err != nil {
		return err
	}

	// 6. 保存站点设置
	if req.SiteTitle != "" || req.SiteSubtitle != "" {
		siteSettings := make(map[string]string)
		if req.SiteTitle != "" {
			siteSettings[constant.KeyTitle] = req.SiteTitle
		}
		if req.SiteSubtitle != "" {
			siteSettings[constant.KeySubtitle] = req.SiteSubtitle
		}
		if err := s.settingsService.SetSection(constant.SectionSite, siteSettings); err != nil {
			logger.Warnf("[Install] 保存站点设置失败: %v", err)
		}
	}

	// 7. 标记已初始化
	if err := s.settingsService.Set(constant.SectionSystem, constant.KeyInitialized, "true"); err != nil {
		return err
	}

	logger.Info("[Install] 安装完成")
	return nil
}

// createConfigFile 创建配置文件
func (s *InstallService) createConfigFile(req *InstallRequest) error {
	// 确保配置目录存在
	configDir := filepath.Dir(constant.ConfigPath)
	if err := os.MkdirAll(configDir, 0755); err != nil {
		return err
	}

	// 创建配置文件
	cfg := ini.Empty()

	// [server] 配置
	serverSection, _ := cfg.NewSection("server")
	serverSection.NewKey("port", "8052")
	serverSection.NewKey("host", "0.0.0.0")
	serverSection.NewKey("cookie_name", "BHToken")

	// [database] 配置
	dbSection, _ := cfg.NewSection("database")
	dbSection.NewKey("type", req.DBType)
	
	if req.DBType == "sqlite" {
		dbPath := req.DBPath
		if dbPath == "" {
			dbPath = constant.DefaultDBPath
		}
		dbSection.NewKey("path", dbPath)
	} else if req.DBType == "mysql" {
		dbSection.NewKey("host", req.DBHost)
		dbSection.NewKey("port", intToStr(req.DBPort))
		dbSection.NewKey("user", req.DBUser)
		dbSection.NewKey("password", req.DBPassword)
		dbSection.NewKey("dbname", req.DBName)
		if req.DBSSLMode != "" {
			dbSection.NewKey("ssl_mode", req.DBSSLMode)
		}
	}
	dbSection.NewKey("table_prefix", "taskpool_")

	// [redis] 配置（如果启用）
	if req.RedisEnabled {
		redisSection, _ := cfg.NewSection("redis")
		redisSection.NewKey("enabled", "true")
		redisSection.NewKey("host", req.RedisHost)
		redisSection.NewKey("port", intToStr(req.RedisPort))
		if req.RedisPassword != "" {
			redisSection.NewKey("password", req.RedisPassword)
		}
		redisSection.NewKey("db", intToStr(req.RedisDB))
	}

	// [security] 配置
	securitySection, _ := cfg.NewSection("security")
	secret := utils.RandomString(32)
	securitySection.NewKey("secret", secret)

	// 保存配置文件
	if err := cfg.SaveTo(constant.ConfigPath); err != nil {
		return err
	}

	logger.Infof("[Install] 配置文件已保存到: %s", constant.ConfigPath)
	return nil
}

// reloadDatabase 重新加载数据库
func (s *InstallService) reloadDatabase(req *InstallRequest) error {
	dbCfg := &database.Config{
		Type:     req.DBType,
		Host:     req.DBHost,
		Port:     req.DBPort,
		User:     req.DBUser,
		Password: req.DBPassword,
		DBName:   req.DBName,
		Path:     req.DBPath,
		SSLMode:  req.DBSSLMode,
	}

	if req.DBType == "sqlite" && req.DBPath == "" {
		dbCfg.Path = constant.DefaultDBPath
	}

	if err := database.Init(dbCfg); err != nil {
		return err
	}

	return nil
}

// createAdmin 创建管理员账号
func (s *InstallService) createAdmin(req *InstallRequest) error {
	// 检查用户是否已存在
	existingUser := s.userService.GetUserByUsername(req.AdminUsername)
	if existingUser != nil {
		logger.Info("[Install] 管理员账号已存在，跳过创建")
		return nil
	}

	email := req.AdminEmail
	if email == "" {
		email = "admin@local"
	}

	s.userService.CreateUser(req.AdminUsername, req.AdminPassword, email, "admin")
	logger.Infof("[Install] 管理员账号创建成功: %s", req.AdminUsername)
	return nil
}

// intToStr 整数转字符串
func intToStr(n int) string {
	if n == 0 {
		return ""
	}
	return utils.IntToStr(n)
}
