package controllers import ( "math" "strconv" "strings" "github.com/gofiber/fiber/v2" "github.com/sujit-baniya/fiber-boilerplate/pkg/models" ) // AiConfigIndex renderiza la vista del panel de configuraciones de IA. func AiConfigIndex(c *fiber.Ctx) error { data := fiber.Map{ "user": c.Locals("user").(map[string]interface{}), "modules": c.Locals("userModules"), } return c.Render("ai_config", data, "layouts/main") } // GetAiConfigs devuelve la lista paginada en JSON. func GetAiConfigs(c *fiber.Ctx) error { page, _ := strconv.Atoi(c.Query("page", "1")) if page < 1 { page = 1 } limit := 20 offset := (page - 1) * limit search := c.Query("search", "") items, total, err := models.GetAllAiConfigs(limit, offset, search) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } // Ocultar la API key en el listado (mostrar solo últimos 4 chars) type safe struct { ID uint `json:"ID"` Nombre string `json:"nombre"` Provider string `json:"provider"` ApiKeyHint string `json:"api_key_hint"` BaseURL string `json:"base_url"` ModelName string `json:"model_name"` IsActive bool `json:"is_active"` Notes string `json:"notes"` } safeItems := make([]safe, len(items)) for i, it := range items { hint := "••••" if len(it.ApiKey) > 4 { hint = "••••" + it.ApiKey[len(it.ApiKey)-4:] } safeItems[i] = safe{ ID: it.ID, Nombre: it.Nombre, Provider: it.Provider, ApiKeyHint: hint, BaseURL: it.BaseURL, ModelName: it.ModelName, IsActive: it.IsActive, Notes: it.Notes, } } return c.JSON(fiber.Map{ "items": safeItems, "total": total, "totalPages": int(math.Ceil(float64(total) / float64(limit))), "page": page, }) } // CreateAiConfigHandler crea una nueva configuración de IA. func CreateAiConfigHandler(c *fiber.Ctx) error { type Req struct { Nombre string `json:"nombre"` Provider string `json:"provider"` ApiKey string `json:"api_key"` BaseURL string `json:"base_url"` ModelName string `json:"model_name"` IsActive bool `json:"is_active"` Notes string `json:"notes"` } var req Req if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"}) } if strings.TrimSpace(req.Nombre) == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "nombre es requerido"}) } if strings.TrimSpace(req.Provider) == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "provider es requerido"}) } if strings.TrimSpace(req.ApiKey) == "" { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "api_key es requerido"}) } item := models.AiConfig{ Nombre: strings.TrimSpace(req.Nombre), Provider: strings.ToLower(strings.TrimSpace(req.Provider)), ApiKey: strings.TrimSpace(req.ApiKey), BaseURL: strings.TrimSpace(req.BaseURL), ModelName: strings.TrimSpace(req.ModelName), IsActive: req.IsActive, Notes: req.Notes, } if err := models.CreateAiConfig(&item); err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"ok": true, "id": item.ID}) } // UpdateAiConfigHandler actualiza una configuración de IA existente. func UpdateAiConfigHandler(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"}) } type Req struct { Nombre string `json:"nombre"` Provider string `json:"provider"` ApiKey string `json:"api_key"` // vacío = no cambiar BaseURL string `json:"base_url"` ModelName string `json:"model_name"` IsActive bool `json:"is_active"` Notes string `json:"notes"` } var req Req if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "body inválido"}) } updates := map[string]interface{}{ "nombre": strings.TrimSpace(req.Nombre), "provider": strings.ToLower(strings.TrimSpace(req.Provider)), "base_url": strings.TrimSpace(req.BaseURL), "model_name": strings.TrimSpace(req.ModelName), "is_active": req.IsActive, "notes": req.Notes, } if strings.TrimSpace(req.ApiKey) != "" { updates["api_key"] = strings.TrimSpace(req.ApiKey) } if err := models.UpdateAiConfig(uint(id), updates); err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"ok": true}) } // DeleteAiConfigHandler elimina una configuración de IA. func DeleteAiConfigHandler(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "id inválido"}) } if err := models.DeleteAiConfig(uint(id)); err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()}) } return c.JSON(fiber.Map{"ok": true}) }