package system

import (
	"context"
	"fmt"
	"path/filepath"
	"strings"

	"gorm.io/gorm"
)

// AutoCodeSqlite SQLite适配器
type AutoCodeSqlite struct {
	db     *gorm.DB
	dbList map[string]*gorm.DB
}

// NewAutoCodeSqlite 创建SQLite适配器
func NewAutoCodeSqlite(db *gorm.DB, dbList map[string]*gorm.DB) *AutoCodeSqlite {
	return &AutoCodeSqlite{
		db:     db,
		dbList: dbList,
	}
}

// GetDB 获取数据库的所有数据库名
func (s *AutoCodeSqlite) GetDB(ctx context.Context) ([]Db, error) {
	var entities []Db
	sql := "PRAGMA database_list;"
	var databaseList []struct {
		File string `gorm:"column:file"`
	}
	err := s.db.WithContext(ctx).Raw(sql).Find(&databaseList).Error
	if err != nil {
		return nil, err
	}
	for _, database := range databaseList {
		if database.File != "" {
			fileName := filepath.Base(database.File)
			fileExt := filepath.Ext(fileName)
			fileNameWithoutExt := strings.TrimSuffix(fileName, fileExt)
			entities = append(entities, Db{Database: fileNameWithoutExt})
		}
	}
	return entities, nil
}

// GetTables 获取数据库的所有表名
func (s *AutoCodeSqlite) GetTables(ctx context.Context, dbName string) ([]Table, error) {
	var entities []Table
	sql := `SELECT name FROM sqlite_master WHERE type='table'`
	var tableNames []string
	err := s.db.WithContext(ctx).Raw(sql).Find(&tableNames).Error
	if err != nil {
		return nil, err
	}
	for _, tableName := range tableNames {
		entities = append(entities, Table{TableName: tableName})
	}
	return entities, nil
}

// GetColumn 获取指定数据表的所有字段名,类型值等
func (s *AutoCodeSqlite) GetColumn(ctx context.Context, tableName, dbName string) ([]Column, error) {
	var entities []Column
	sql := fmt.Sprintf("PRAGMA table_info(%s);", tableName)
	var columnInfos []struct {
		Name string `gorm:"column:name"`
		Type string `gorm:"column:type"`
		Pk   int    `gorm:"column:pk"`
	}
	err := s.db.WithContext(ctx).Raw(sql).Scan(&columnInfos).Error
	if err != nil {
		return nil, err
	}
	for _, columnInfo := range columnInfos {
		pk := 0
		if columnInfo.Pk == 1 {
			pk = 1
		}
		entities = append(entities, Column{
			ColumnName: columnInfo.Name,
			DataType:   columnInfo.Type,
			PrimaryKey: pk,
		})
	}
	return entities, nil
}
