turash/bugulma/backend/internal/handler/ai_handler.go
Damir Mukimov 000eab4740
Major repository reorganization and missing backend endpoints implementation
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools

Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
  * GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
  * GET /api/v1/users/me/organizations - User organizations
  * POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue

API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules

Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
2025-11-25 06:01:16 +01:00

236 lines
6.8 KiB
Go

package handler
import (
"net/http"
"bugulma/backend/internal/service"
"github.com/gin-gonic/gin"
)
// AIHandler handles AI-powered functionality
type AIHandler struct {
service *service.AIService
}
// NewAIHandler creates a new AI handler
func NewAIHandler(service *service.AIService) *AIHandler {
return &AIHandler{service: service}
}
// ExtractFromText extracts organization data from text
// @Summary Extract organization data from text
// @Tags ai
// @Accept multipart/form-data
// @Produce json
// @Param text formData string true "Text to extract from"
// @Success 200 {object} map[string]interface{}
// @Router /ai/extract/text [post]
func (h *AIHandler) ExtractFromText(c *gin.Context) {
text := c.PostForm("text")
if text == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "text parameter is required"})
return
}
result, err := h.service.ExtractDataFromText(c.Request.Context(), text)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// ExtractFromFile extracts organization data from file
// @Summary Extract organization data from file
// @Tags ai
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "File to extract from"
// @Success 200 {object} map[string]interface{}
// @Router /ai/extract/file [post]
func (h *AIHandler) ExtractFromFile(c *gin.Context) {
file, header, err := c.Request.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "file parameter is required"})
return
}
defer file.Close()
// Read file data
fileData := make([]byte, header.Size)
_, err = file.Read(fileData)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to read file"})
return
}
result, err := h.service.ExtractDataFromFile(c.Request.Context(), fileData, header.Filename)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// AnalyzeSymbiosis analyzes symbiotic relationships
// @Summary Analyze symbiotic relationships
// @Tags ai
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "Analysis request"
// @Success 200 {array} map[string]interface{}
// @Router /ai/analyze/symbiosis [post]
func (h *AIHandler) AnalyzeSymbiosis(c *gin.Context) {
var request map[string]interface{}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
orgID, _ := request["organization_id"].(string)
result, err := h.service.AnalyzeSymbiosis(c.Request.Context(), orgID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// GetWebIntelligence gets web intelligence
// @Summary Get web intelligence
// @Tags ai
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "Web intelligence request"
// @Success 200 {object} map[string]interface{}
// @Router /ai/web-intelligence [post]
func (h *AIHandler) GetWebIntelligence(c *gin.Context) {
var request map[string]interface{}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
orgName, _ := request["organization_name"].(string)
result, err := h.service.GetWebIntelligence(c.Request.Context(), orgName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// GetSearchSuggestions gets search suggestions
// @Summary Get search suggestions
// @Tags ai
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "Search suggestions request"
// @Success 200 {array} string
// @Router /ai/search-suggestions [post]
func (h *AIHandler) GetSearchSuggestions(c *gin.Context) {
var request map[string]interface{}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
query, _ := request["query"].(string)
result, err := h.service.GetSearchSuggestions(c.Request.Context(), query)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// GenerateDescription generates organization description
// @Summary Generate organization description
// @Tags ai
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "Description generation request"
// @Success 200 {string} string
// @Router /ai/generate/description [post]
func (h *AIHandler) GenerateDescription(c *gin.Context) {
var request map[string]interface{}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
name, _ := request["name"].(string)
sector, _ := request["sector"].(string)
keywords, _ := request["keywords"].(string)
result, err := h.service.GenerateDescription(c.Request.Context(), name, sector, keywords)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// GenerateHistoricalContext generates historical context
// @Summary Generate historical context
// @Tags ai
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "Historical context request"
// @Success 200 {string} string
// @Router /ai/generate/historical-context [post]
func (h *AIHandler) GenerateHistoricalContext(c *gin.Context) {
var request map[string]interface{}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
landmarkName, _ := request["landmark_name"].(string)
period, _ := request["period"].(string)
originalPurpose, _ := request["original_purpose"].(string)
currentStatus, _ := request["current_status"].(string)
result, err := h.service.GenerateHistoricalContext(c.Request.Context(), landmarkName, period, originalPurpose, currentStatus)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}
// SendMessage sends a chat message
// @Summary Send chat message
// @Tags ai
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "Chat message request"
// @Success 200 {string} string
// @Router /ai/chat [post]
func (h *AIHandler) SendMessage(c *gin.Context) {
var request map[string]interface{}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
message, _ := request["message"].(string)
systemInstruction, _ := request["system_instruction"].(string)
result, err := h.service.SendMessage(c.Request.Context(), message, systemInstruction)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, result)
}