package models

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"

	"github.com/sujit-baniya/fiber-boilerplate/app"
	"gorm.io/gorm"
)

// UmindCanal es un canal de mensajería adicional (Telegram, WhatsApp) que
// alimenta al mismo agente del tenant que ya atiende el widget web. Los
// secretos reales (bot token, access token de WhatsApp, etc.) viven cifrados
// en CredencialesEnc (ver pkg/services/umind_secrets.go) — el modelo solo
// persiste el string ya cifrado, no conoce la clave.
//
// WebhookSecret es un identificador público generado por nosotros, distinto
// del secreto real del proveedor, usado SOLO para enrutar el webhook
// entrante al canal correcto (va en la URL que se registra en
// Telegram/Meta). Evita que el token real del proveedor termine en logs de
// acceso o de un proxy intermedio.
type UmindCanal struct {
	gorm.Model
	AgenteID        uint   `json:"agente_id" gorm:"column:agente_id;index"`
	Tipo            string `json:"tipo" gorm:"column:tipo;size:20;not null"` // telegram | whatsapp
	Activo          bool   `json:"activo" gorm:"column:activo;default:true"`
	WebhookSecret   string `json:"webhook_secret" gorm:"column:webhook_secret;uniqueIndex;size:40;not null"`
	CredencialesEnc string `json:"-" gorm:"column:credenciales_enc;type:text"`
	UltimoError     string `json:"ultimo_error" gorm:"column:ultimo_error;type:text"`
	// Si están activos, los mensajes de voz/audio e imágenes que llegan por
	// este canal se transcriben (Whisper) o se les extrae el texto (OCR)
	// antes de pasarlos al agente, en vez de ignorarse.
	UsarWhisperAudio bool `json:"usar_whisper_audio" gorm:"column:usar_whisper_audio;default:false"`
	UsarOcrImagenes  bool `json:"usar_ocr_imagenes" gorm:"column:usar_ocr_imagenes;default:false"`
}

func (UmindCanal) TableName() string { return "umind_canales" }

func GenerarWebhookSecret() (string, error) {
	b := make([]byte, 16)
	if _, err := rand.Read(b); err != nil {
		return "", fmt.Errorf("no se pudo generar el webhook_secret: %w", err)
	}
	return "umc_" + hex.EncodeToString(b), nil
}

func CreateUmindCanal(c *UmindCanal) error {
	if c.WebhookSecret == "" {
		secret, err := GenerarWebhookSecret()
		if err != nil {
			return err
		}
		c.WebhookSecret = secret
	}
	return app.Http.Database.DB.Create(c).Error
}

func GetUmindCanalesByAgente(agenteID uint) ([]UmindCanal, error) {
	var items []UmindCanal
	err := app.Http.Database.DB.Where("agente_id = ?", agenteID).Order("id DESC").Find(&items).Error
	return items, err
}

func GetUmindCanalByID(id uint) (*UmindCanal, error) {
	var c UmindCanal
	if err := app.Http.Database.DB.First(&c, id).Error; err != nil {
		return nil, err
	}
	return &c, nil
}

// GetUmindCanalByWebhookSecret resuelve el canal a partir del identificador
// público que viene en la URL del webhook. Solo matchea si está activo.
func GetUmindCanalByWebhookSecret(tipo, webhookSecret string) (*UmindCanal, error) {
	var c UmindCanal
	err := app.Http.Database.DB.Where("tipo = ? AND webhook_secret = ? AND activo = ?", tipo, webhookSecret, true).First(&c).Error
	if err != nil {
		return nil, err
	}
	return &c, nil
}

func UpdateUmindCanal(id uint, updates map[string]interface{}) error {
	return app.Http.Database.DB.Model(&UmindCanal{}).Where("id = ?", id).Updates(updates).Error
}

func DeleteUmindCanal(id uint) error {
	return app.Http.Database.DB.Delete(&UmindCanal{}, id).Error
}
