package system

import (
	"context"

	"kra/internal/biz/system"
	"kra/internal/conf"

	"gorm.io/gorm"
)

type autoCodeRepo struct {
	db     *gorm.DB
	dbName string
	conf   *conf.Bootstrap
}

// NewAutoCodeRepo 创建自动代码仓储
func NewAutoCodeRepo(db *gorm.DB, conf *conf.Bootstrap) system.AutoCodeRepo {
	// 获取默认数据库名
	dbName := ""
	if conf.Mysql != nil && conf.Mysql.DbName != "" {
		dbName = conf.Mysql.DbName
	} else if conf.Pgsql != nil && conf.Pgsql.DbName != "" {
		dbName = conf.Pgsql.DbName
	} else if conf.Sqlite != nil && conf.Sqlite.DbName != "" {
		dbName = conf.Sqlite.DbName
	}
	return &autoCodeRepo{
		db:     db,
		dbName: dbName,
		conf:   conf,
	}
}

// GetDB 获取所有数据库
func (r *autoCodeRepo) GetDB(ctx context.Context, businessDB string) ([]system.Db, error) {
	var entities []system.Db
	sql := "SELECT SCHEMA_NAME AS `database` FROM INFORMATION_SCHEMA.SCHEMATA;"
	err := r.db.WithContext(ctx).Raw(sql).Scan(&entities).Error
	return entities, err
}

// GetTables 获取指定数据库的所有表
func (r *autoCodeRepo) GetTables(ctx context.Context, businessDB, dbName string) ([]system.Table, error) {
	var entities []system.Table
	sql := `SELECT table_name AS table_name FROM information_schema.tables WHERE table_schema = ?`
	err := r.db.WithContext(ctx).Raw(sql, dbName).Scan(&entities).Error
	return entities, err
}

// GetColumn 获取指定表的所有列
func (r *autoCodeRepo) GetColumn(ctx context.Context, businessDB, tableName, dbName string) ([]system.Column, error) {
	var entities []system.Column
	sql := `
	SELECT 
		c.COLUMN_NAME column_name,
		c.DATA_TYPE data_type,
		CASE c.DATA_TYPE
			WHEN 'longtext' THEN c.CHARACTER_MAXIMUM_LENGTH
			WHEN 'varchar' THEN c.CHARACTER_MAXIMUM_LENGTH
			WHEN 'double' THEN CONCAT_WS(',', c.NUMERIC_PRECISION, c.NUMERIC_SCALE)
			WHEN 'decimal' THEN CONCAT_WS(',', c.NUMERIC_PRECISION, c.NUMERIC_SCALE)
			WHEN 'int' THEN c.NUMERIC_PRECISION
			WHEN 'bigint' THEN c.NUMERIC_PRECISION
			ELSE '' 
		END AS data_type_long,
		c.COLUMN_COMMENT column_comment,
		CASE WHEN kcu.COLUMN_NAME IS NOT NULL THEN 1 ELSE 0 END AS primary_key,
		c.ORDINAL_POSITION
	FROM 
		INFORMATION_SCHEMA.COLUMNS c
	LEFT JOIN 
		INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu 
	ON 
		c.TABLE_SCHEMA = kcu.TABLE_SCHEMA 
		AND c.TABLE_NAME = kcu.TABLE_NAME 
		AND c.COLUMN_NAME = kcu.COLUMN_NAME 
		AND kcu.CONSTRAINT_NAME = 'PRIMARY'
	WHERE 
		c.TABLE_NAME = ? 
		AND c.TABLE_SCHEMA = ?
	ORDER BY 
		c.ORDINAL_POSITION;`
	err := r.db.WithContext(ctx).Raw(sql, tableName, dbName).Scan(&entities).Error
	return entities, err
}

// GetDBList 获取配置的数据库列表
func (r *autoCodeRepo) GetDBList() []system.DBInfo {
	// 目前KRA只支持单数据库配置，返回主数据库信息
	var dbList []system.DBInfo
	if r.conf.Mysql != nil && r.conf.Mysql.DbName != "" {
		dbList = append(dbList, system.DBInfo{
			AliasName: "",
			DBName:    r.conf.Mysql.DbName,
			Disable:   false,
			DBType:    "mysql",
		})
	}
	if r.conf.Pgsql != nil && r.conf.Pgsql.DbName != "" {
		dbList = append(dbList, system.DBInfo{
			AliasName: "",
			DBName:    r.conf.Pgsql.DbName,
			Disable:   false,
			DBType:    "pgsql",
		})
	}
	if r.conf.Sqlite != nil && r.conf.Sqlite.DbName != "" {
		dbList = append(dbList, system.DBInfo{
			AliasName: "",
			DBName:    r.conf.Sqlite.DbName,
			Disable:   false,
			DBType:    "sqlite",
		})
	}
	return dbList
}

// GetActiveDBName 获取当前活动的数据库名
func (r *autoCodeRepo) GetActiveDBName(businessDB string) string {
	// 目前KRA只支持单数据库，直接返回配置的数据库名
	return r.dbName
}
