package database import ( "fmt" "log" "os" "time" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" "customer-support-system/internal/models" ) var DB *gorm.DB // Connect initializes the database connection func Connect() error { dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=%s TimeZone=%s", getEnv("DB_HOST", "localhost"), getEnv("DB_USER", "postgres"), getEnv("DB_PASSWORD", "postgres"), getEnv("DB_NAME", "support"), getEnv("DB_PORT", "5432"), getEnv("DB_SSLMODE", "disable"), getEnv("DB_TIMEZONE", "UTC"), ) newLogger := logger.New( log.New(os.Stdout, "\n", log.LstdFlags), logger.Config{ SlowThreshold: time.Second, LogLevel: logger.Info, Colorful: false, }, ) var err error DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: newLogger, }) if err != nil { return fmt.Errorf("failed to connect to database: %w", err) } log.Println("Database connected successfully") return nil } // AutoMigrate runs the database migrations func AutoMigrate() error { err := DB.AutoMigrate( &models.User{}, &models.Conversation{}, &models.Message{}, &models.KnowledgeBase{}, &models.KnowledgeBaseFeedback{}, &models.AIModel{}, &models.AIInteraction{}, &models.AIFallback{}, ) if err != nil { return fmt.Errorf("failed to run database migrations: %w", err) } log.Println("Database migrations completed successfully") return nil } // Close closes the database connection func Close() error { sqlDB, err := DB.DB() if err != nil { return fmt.Errorf("failed to get database instance: %w", err) } err = sqlDB.Close() if err != nil { return fmt.Errorf("failed to close database connection: %w", err) } log.Println("Database connection closed successfully") return nil } // GetDB returns the database instance func GetDB() *gorm.DB { return DB } // getEnv gets an environment variable with a default value func getEnv(key, defaultValue string) string { if value, exists := os.LookupEnv(key); exists { return value } return defaultValue } // SeedDatabase seeds the database with initial data func SeedDatabase() error { // Create default admin user if not exists var userCount int64 if err := DB.Model(&models.User{}).Where("role = ?", "admin").Count(&userCount).Error; err != nil { return fmt.Errorf("failed to count admin users: %w", err) } if userCount == 0 { adminUser := models.User{ Username: "admin", Email: "admin@example.com", Password: "admin123", FirstName: "Admin", LastName: "User", Role: "admin", Active: true, } if err := DB.Create(&adminUser).Error; err != nil { return fmt.Errorf("failed to create admin user: %w", err) } log.Println("Default admin user created") } // Create default AI models if not exists var aiModelCount int64 if err := DB.Model(&models.AIModel{}).Count(&aiModelCount).Error; err != nil { return fmt.Errorf("failed to count AI models: %w", err) } if aiModelCount == 0 { // Create OpenAI GPT-4 model openAIModel := models.AIModel{ Name: "OpenAI GPT-4", Type: "openai", Model: "gpt-4", MaxTokens: 4000, Temperature: 0.7, TopP: 1.0, Active: true, Priority: 2, Description: "OpenAI's GPT-4 model for complex queries", } if err := DB.Create(&openAIModel).Error; err != nil { return fmt.Errorf("failed to create OpenAI model: %w", err) } // Create Local LLaMA model localModel := models.AIModel{ Name: "Local LLaMA", Type: "local", Model: "llama2", Endpoint: "http://localhost:11434", MaxTokens: 2000, Temperature: 0.7, TopP: 1.0, Active: true, Priority: 1, Description: "Local LLaMA model for simple queries", } if err := DB.Create(&localModel).Error; err != nil { return fmt.Errorf("failed to create local model: %w", err) } log.Println("Default AI models created") } // Create sample knowledge base entries if not exists var kbCount int64 if err := DB.Model(&models.KnowledgeBase{}).Count(&kbCount).Error; err != nil { return fmt.Errorf("failed to count knowledge base entries: %w", err) } if kbCount == 0 { sampleEntries := []models.KnowledgeBase{ { Question: "How do I reset my password?", Answer: "To reset your password, click on the 'Forgot Password' link on the login page. Enter your email address and follow the instructions sent to your inbox.", Category: "Account", Tags: "password,reset,account", Priority: 5, Active: true, }, { Question: "What payment methods do you accept?", Answer: "We accept all major credit cards including Visa, Mastercard, and American Express. We also support payments through PayPal and bank transfers.", Category: "Billing", Tags: "payment,billing,methods", Priority: 4, Active: true, }, { Question: "How can I contact customer support?", Answer: "You can contact our customer support team through the chat feature on our website, by emailing support@example.com, or by calling our toll-free number at 1-800-123-4567.", Category: "Support", Tags: "contact,support,help", Priority: 3, Active: true, }, } for _, entry := range sampleEntries { if err := DB.Create(&entry).Error; err != nil { return fmt.Errorf("failed to create knowledge base entry: %w", err) } } log.Println("Sample knowledge base entries created") } return nil }