package models

import (
	"fmt"
	"time"

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

type NotificacionLog struct {
	gorm.Model
	ClienteID    uint              `json:"cliente_id" gorm:"column:cliente_id"`
	Cliente      Cliente           `json:"cliente" gorm:"foreignKey:ClienteID"`
	ReglaID      uint              `json:"regla_id" gorm:"column:regla_id"`
	Regla        NotificacionRegla `json:"regla" gorm:"foreignKey:ReglaID"`
	ContratosIDs string            `json:"contratos_ids" gorm:"column:contratos_ids;type:text"` // JSON array
	FechaEnvio   time.Time         `json:"fecha_envio" gorm:"column:fecha_envio"`
	Estado       string            `json:"estado" gorm:"column:estado;default:'pendiente'"` // enviado | fallido | pendiente
	ErrorMsg     string            `json:"error_msg" gorm:"column:error_msg;type:text"`
	Asunto       string            `json:"asunto" gorm:"column:asunto"`
	PreviewHTML  string            `json:"preview_html" gorm:"column:preview_html;type:text"`
	Pasarela     string            `json:"pasarela" gorm:"column:pasarela;type:varchar(20)"` // bold | dlocal | (vacío para correos de aviso)
	EnlacePago   string            `json:"enlace_pago" gorm:"column:enlace_pago;type:text"`  // URL del link de pago generado en este envío
}

func (NotificacionLog) TableName() string { return "notificaciones_log" }

func GetAllNotificacionLogs(limit, offset int, clienteID uint, estado string) ([]NotificacionLog, int64, error) {
	var items []NotificacionLog
	var total int64
	db := app.Http.Database.DB.Model(&NotificacionLog{}).
		Preload("Cliente").Preload("Regla")
	if clienteID > 0 {
		db = db.Where("cliente_id = ?", clienteID)
	}
	if estado != "" {
		db = db.Where("estado = ?", estado)
	}
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if err := db.Order("created_at DESC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
		return nil, 0, err
	}
	return items, total, nil
}

func GetNotificacionLogByID(id uint) (*NotificacionLog, error) {
	var item NotificacionLog
	if err := app.Http.Database.DB.Preload("Cliente").Preload("Regla").First(&item, id).Error; err != nil {
		return nil, err
	}
	return &item, nil
}

// YaEnviadoHoy comprueba si ya se envió notificación de esta regla a este cliente hoy
func YaEnviadoHoy(clienteID, reglaID uint) bool {
	var count int64
	today := time.Now().UTC().Truncate(24 * time.Hour)
	tomorrow := today.Add(24 * time.Hour)
	app.Http.Database.DB.Model(&NotificacionLog{}).
		Where("cliente_id = ? AND regla_id = ? AND estado = 'enviado' AND created_at >= ? AND created_at < ?",
			clienteID, reglaID, today, tomorrow).
		Count(&count)
	return count > 0
}

func CreateNotificacionLog(n NotificacionLog) (*NotificacionLog, error) {
	if err := app.Http.Database.DB.Create(&n).Error; err != nil {
		return nil, err
	}
	return &n, nil
}

func UpdateNotificacionLog(n NotificacionLog) error {
	return app.Http.Database.DB.Model(&n).Updates(map[string]interface{}{
		"estado":      n.Estado,
		"error_msg":   n.ErrorMsg,
		"pasarela":    n.Pasarela,
		"enlace_pago": n.EnlacePago,
	}).Error
}

// Aliases simples para los controllers
func GetAllLogs(limit, offset int) ([]NotificacionLog, int64, error) {
	return GetAllNotificacionLogs(limit, offset, 0, "")
}

func GetLogByID(id uint) (*NotificacionLog, error) {
	return GetNotificacionLogByID(id)
}

// GetLogsByContratoID devuelve los logs de notificaciones que incluyen un contrato específico
func GetLogsByContratoID(contratoID uint) ([]NotificacionLog, error) {
	var items []NotificacionLog
	// contratos_ids es un JSON array, buscamos que contenga el ID
	pattern := fmt.Sprintf(`%%[%d]%%`, contratoID)
	if err := app.Http.Database.DB.
		Preload("Regla").
		Where("contratos_ids LIKE ?", pattern).
		Order("created_at DESC").
		Limit(50).
		Find(&items).Error; err != nil {
		return nil, err
	}
	return items, nil
}
