package models

import (
	"time"

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

// ─── Factura ──────────────────────────────────────────────────────────────────

type Factura struct {
	gorm.Model
	ClienteID        uint       `json:"cliente_id"        gorm:"column:cliente_id;index;not null"`
	Cliente          Cliente    `json:"cliente"           gorm:"foreignKey:ClienteID"`
	ProyectoID       *uint      `json:"proyecto_id"       gorm:"column:proyecto_id;index"`
	Proyecto         *Proyecto  `json:"proyecto"          gorm:"foreignKey:ProyectoID"`
	Numero           string     `json:"numero"            gorm:"column:numero"`
	Descripcion      string     `json:"descripcion"       gorm:"column:descripcion;type:text"`
	Monto            float64    `json:"monto"             gorm:"column:monto"`
	Moneda           string     `json:"moneda"            gorm:"column:moneda;default:'COP'"`
	Estado           string     `json:"estado"            gorm:"column:estado;default:'pendiente'"` // pendiente|pagada|vencida|cancelada
	FechaEmision     time.Time  `json:"fecha_emision"     gorm:"column:fecha_emision"`
	FechaVencimiento *time.Time `json:"fecha_vencimiento" gorm:"column:fecha_vencimiento"`
	Archivo          string     `json:"archivo"           gorm:"column:archivo"`
	OriginalName     string     `json:"original_name"     gorm:"column:original_name"`
	Visible          bool       `json:"visible"           gorm:"column:visible;default:true"`
	Notas            string     `json:"notas"             gorm:"column:notas;type:text"`
}

func (Factura) TableName() string { return "facturas" }

// ─── CRUD ─────────────────────────────────────────────────────────────────────

func GetAllFacturas(limit, offset int, search string) ([]Factura, int64, error) {
	var items []Factura
	var total int64
	db := app.Http.Database.DB.Model(&Factura{}).Preload("Cliente").Preload("Proyecto")
	if search != "" {
		db = db.Joins("JOIN clientes ON clientes.id = facturas.cliente_id").
			Where("facturas.numero ILIKE ? OR clientes.nombre ILIKE ? OR clientes.empresa ILIKE ?",
				"%"+search+"%", "%"+search+"%", "%"+search+"%")
	}
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if err := db.Order("facturas.fecha_emision DESC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
		return nil, 0, err
	}
	return items, total, nil
}

func GetFacturasByCliente(clienteID uint, soloVisibles bool) ([]Factura, error) {
	var items []Factura
	db := app.Http.Database.DB.Where("cliente_id = ?", clienteID)
	if soloVisibles {
		db = db.Where("visible = true")
	}
	err := db.Preload("Proyecto").Order("fecha_emision DESC").Find(&items).Error
	return items, err
}

func GetFacturaByID(id uint) (*Factura, error) {
	var item Factura
	err := app.Http.Database.DB.Preload("Cliente").Preload("Proyecto").First(&item, id).Error
	return &item, err
}

func CreateFactura(f *Factura) error {
	return app.Http.Database.DB.Create(f).Error
}

func UpdateFactura(f *Factura) error {
	return app.Http.Database.DB.Model(&Factura{}).Where("id = ?", f.ID).Updates(map[string]interface{}{
		"cliente_id":        f.ClienteID,
		"proyecto_id":       f.ProyectoID,
		"numero":            f.Numero,
		"descripcion":       f.Descripcion,
		"monto":             f.Monto,
		"moneda":            f.Moneda,
		"estado":            f.Estado,
		"fecha_emision":     f.FechaEmision,
		"fecha_vencimiento": f.FechaVencimiento,
		"visible":           f.Visible,
		"notas":             f.Notas,
	}).Error
}

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

func UpdateFacturaArchivo(id uint, archivo, originalName string) error {
	return app.Http.Database.DB.Model(&Factura{}).Where("id = ?", id).Updates(map[string]interface{}{
		"archivo":       archivo,
		"original_name": originalName,
	}).Error
}
