package model

import (
	"fmt"

	"github.com/veypi/vbase/internal/config"
	"gorm.io/driver/mysql"
	"gorm.io/driver/postgres"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var DB *gorm.DB

// InitDB 初始化数据库
func InitDB() error {
	cfg := config.C.Database

	var dialector gorm.Dialector
	switch cfg.Type {
	case "mysql":
		dialector = mysql.Open(cfg.DSN)
	case "postgres":
		dialector = postgres.Open(cfg.DSN)
	case "sqlite":
		dialector = sqlite.Open(cfg.DSN)
	default:
		return fmt.Errorf("unsupported database type: %s", cfg.Type)
	}

	var err error
	DB, err = gorm.Open(dialector, &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		return fmt.Errorf("failed to connect database: %w", err)
	}

	sqlDB, err := DB.DB()
	if err != nil {
		return err
	}

	sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)
	sqlDB.SetMaxIdleConns(cfg.MaxIdleConns)
	sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime)

	return nil
}

// AutoMigrate 自动迁移表结构
func AutoMigrate() error {
	return DB.AutoMigrate(
		&User{},
		&Identity{},
		&Session{},
		&Org{},
		&OrgMember{},
		&Policy{},
		&Role{},
		&OAuthClient{},
		&OAuthAuthorization{},
		&OAuthToken{},
	)
}

// InitSystemData 初始化系统数据
func InitSystemData() error {
	return DB.Transaction(func(tx *gorm.DB) error {
		// 1. 创建系统策略
		if err := initSystemPolicies(tx); err != nil {
			return err
		}

		// 2. 检查是否需要创建初始管理员
		var count int64
		if err := tx.Model(&User{}).Count(&count).Error; err != nil {
			return err
		}

		if count == 0 {
			if err := initAdminUser(tx); err != nil {
				return err
			}
		}

		return nil
	})
}

// initSystemPolicies 创建系统内置策略
func initSystemPolicies(tx *gorm.DB) error {
	policies := []Policy{
		{
			Code:        SysPolicyUserReadOwn,
			Name:        "读取自己",
			Description: "用户读取自己的信息",
			Resource:    "user",
			Action:      "read",
			Condition:   "resource.id == user.id",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyUserUpdateOwn,
			Name:        "更新自己",
			Description: "用户更新自己的信息",
			Resource:    "user",
			Action:      "update",
			Condition:   "resource.id == user.id",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyUserDeleteOwn,
			Name:        "删除自己",
			Description: "用户删除自己的账号",
			Resource:    "user",
			Action:      "delete",
			Condition:   "resource.id == user.id",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyOrgAdmin,
			Name:        "组织管理员",
			Description: "组织所有者拥有所有权限",
			Resource:    "*",
			Action:      "*",
			Condition:   "org.owner_id == user.id",
			Effect:      EffectAllow,
			Priority:    100,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyOrgRead,
			Name:        "读取组织",
			Description: "组织成员可读组织信息",
			Resource:    "org",
			Action:      "read",
			Condition:   "member.org_id == org.id",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyMemberRead,
			Name:        "读取成员",
			Description: "读取组织成员列表",
			Resource:    "member",
			Action:      "read",
			Condition:   "member.org_id == org.id",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyMemberManage,
			Name:        "管理成员",
			Description: "管理组织成员",
			Resource:    "member",
			Action:      "*",
			Condition:   "",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyRoleRead,
			Name:        "读取角色",
			Description: "读取组织角色",
			Resource:    "role",
			Action:      "read",
			Condition:   "resource.org_id == org.id",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyRoleManage,
			Name:        "管理角色",
			Description: "管理组织角色",
			Resource:    "role",
			Action:      "*",
			Condition:   "",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyPolicyRead,
			Name:        "读取策略",
			Description: "读取策略",
			Resource:    "policy",
			Action:      "read",
			Condition:   "",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
		{
			Code:        SysPolicyPolicyManage,
			Name:        "管理策略",
			Description: "管理策略",
			Resource:    "policy",
			Action:      "*",
			Condition:   "",
			Effect:      EffectAllow,
			IsSystem:    true,
		},
	}

	for _, p := range policies {
		var existing Policy
		if err := tx.Where("code = ?", p.Code).First(&existing).Error; err != nil {
			if err == gorm.ErrRecordNotFound {
				if err := tx.Create(&p).Error; err != nil {
					return err
				}
			} else {
				return err
			}
		}
	}

	return nil
}

// initAdminUser 创建初始管理员
func initAdminUser(tx *gorm.DB) error {
	adminCfg := config.C.App.InitAdmin

	// 生成随机密码（如果未配置）
	password := adminCfg.Password
	if password == "" {
		password = generateRandomPassword(16)
		fmt.Printf("\n========================================\n")
		fmt.Printf("Initial admin user created!\n")
		fmt.Printf("Username: %s\n", adminCfg.Username)
		fmt.Printf("Password: %s\n", password)
		fmt.Printf("Email: %s\n", adminCfg.Email)
		fmt.Printf("========================================\n\n")
	}

	// 密码哈希（这里需要crypto包，后续实现）
	// hashedPassword, _ := crypto.HashPassword(password)

	admin := &User{
		Username:      adminCfg.Username,
		Password:      password, // TODO: hash password
		Email:         adminCfg.Email,
		Nickname:      "Administrator",
		Status:        UserStatusActive,
		EmailVerified: true,
		PhoneVerified: false,
	}

	if err := tx.Create(admin).Error; err != nil {
		return err
	}

	return nil
}

// generateRandomPassword 生成随机密码
func generateRandomPassword(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*"
	result := make([]byte, length)
	for i := range result {
		result[i] = charset[i%len(charset)]
	}
	return string(result)
}
