package main

import (
	"fmt"
	"path/filepath"
	"runtime"

	"gorm.io/driver/mysql"
	"gorm.io/gen"
	"gorm.io/gen/field"
	"gorm.io/gorm"
)

func main() {
	// 连接数据库
	dsn := "root:Xu950329.@tcp(localhost:3306)/spa?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(fmt.Errorf("connect db fail: %w", err))
	}

	// 获取项目根目录
	_, filename, _, _ := runtime.Caller(0)
	projectRoot := filepath.Dir(filepath.Dir(filepath.Dir(filename)))

	// 创建gen实例
	g := gen.NewGenerator(gen.Config{
		OutPath:           filepath.Join(projectRoot, "internal/data/query"),
		ModelPkgPath:      filepath.Join(projectRoot, "internal/data/model"),
		Mode:              gen.WithDefaultQuery | gen.WithQueryInterface,
		FieldNullable:     false, // 非NULL字段生成为值类型
		FieldCoverable:    false,
		FieldSignable:     false,
		FieldWithIndexTag: true,
		FieldWithTypeTag:  true,
	})

	g.UseDB(db)

	// 字段名映射，避免与方法名冲突
	fieldOpts := []gen.ModelOpt{
		gen.FieldRename("table_name", "TblName"),
		gen.FieldRename("table", "TblName"),
	}

	// SysUser 关联配置
	sysUserOpts := append(fieldOpts,
		// Authority: belongs to SysAuthority
		gen.FieldRelate(field.HasOne, "Authority", g.GenerateModel("sys_authorities"),
			&field.RelateConfig{
				GORMTag: field.GormTag{
					"foreignKey": []string{"AuthorityID"},
					"references": []string{"AuthorityID"},
				},
			}),
		// Authorities: many2many through sys_user_authority
		gen.FieldRelate(field.Many2Many, "Authorities", g.GenerateModel("sys_authorities"),
			&field.RelateConfig{
				GORMTag: field.GormTag{
					"many2many":      []string{"sys_user_authority"},
					"joinForeignKey": []string{"SysUserID"},
					"joinReferences": []string{"SysAuthorityAuthorityID"},
				},
			}),
	)

	// 生成带关联的SysUser
	sysUser := g.GenerateModel("sys_users", sysUserOpts...)

	// 生成其他表（不含sys_users）
	tables, _ := db.Migrator().GetTables()
	var models []interface{}
	for _, table := range tables {
		if table == "sys_users" {
			continue
		}
		models = append(models, g.GenerateModel(table, fieldOpts...))
	}

	g.ApplyBasic(sysUser)
	g.ApplyBasic(models...)

	// 执行生成
	g.Execute()
}
