package models

import (
	"fmt"
	"log"
	"time"

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

// ─── Cuenta (plan de cuentas / categoría contable) ───────────────────────────

type Cuenta struct {
	gorm.Model
	Codigo string `json:"codigo" gorm:"column:codigo;size:20"`
	Nombre string `json:"nombre" gorm:"column:nombre;size:255;not null"`
	Tipo   string `json:"tipo" gorm:"column:tipo;size:20;not null"` // ingreso | egreso
	Color  string `json:"color" gorm:"column:color;size:7"`
	Activo bool   `json:"activo" gorm:"column:activo;default:true"`
}

func (Cuenta) TableName() string { return "contab_cuentas" }

// ─── Entidad (cliente, proveedor, empresa, persona) ──────────────────────────

type Entidad struct {
	gorm.Model
	Nombre    string `json:"nombre" gorm:"column:nombre;size:255;not null"`
	Tipo      string `json:"tipo" gorm:"column:tipo;size:20"` // cliente | proveedor | ambos
	Documento string `json:"documento" gorm:"column:documento;size:50"`
	Email     string `json:"email" gorm:"column:email;size:255"`
	Telefono  string `json:"telefono" gorm:"column:telefono;size:50"`
	Contacto  string `json:"contacto" gorm:"column:contacto;size:255"`
	Notas     string `json:"notas" gorm:"column:notas;type:text"`
	Activo    bool   `json:"activo" gorm:"column:activo;default:true"`
}

func (Entidad) TableName() string { return "contab_entidades" }

// ─── Transaccion (ingreso / egreso) ──────────────────────────────────────────

type Transaccion struct {
	gorm.Model
	Fecha       time.Time `json:"fecha" gorm:"column:fecha;not null"`
	Tipo        string    `json:"tipo" gorm:"column:tipo;size:10;not null"` // ingreso | egreso
	Descripcion string    `json:"descripcion" gorm:"column:descripcion;type:text"`
	Valor       float64   `json:"valor" gorm:"column:valor;not null"`
	CuentaID    *uint     `json:"cuenta_id" gorm:"column:cuenta_id;index"`
	Cuenta      *Cuenta   `json:"cuenta" gorm:"foreignKey:CuentaID"`
	EntidadID   *uint     `json:"entidad_id" gorm:"column:entidad_id;index"`
	Entidad     *Entidad  `json:"entidad" gorm:"foreignKey:EntidadID"`
	FormaPago   string    `json:"forma_pago" gorm:"column:forma_pago;size:30"` // transferencia | efectivo | tarjeta | cheque | otro
	Estado      string    `json:"estado" gorm:"column:estado;size:20;default:'registrada'"`
	Notas       string    `json:"notas" gorm:"column:notas;type:text"`
}

func (Transaccion) TableName() string { return "contab_transacciones" }

// ─── CuentaCobro (cuentas por cobrar) ────────────────────────────────────────

type CuentaCobro struct {
	gorm.Model
	ClienteID        uint         `json:"cliente_id" gorm:"column:cliente_id;index;not null"`
	Cliente          Cliente      `json:"cliente" gorm:"foreignKey:ClienteID"`
	EntidadID        *uint        `json:"entidad_id" gorm:"column:entidad_id;index"`
	Entidad          *Entidad     `json:"entidad" gorm:"foreignKey:EntidadID"`
	Fecha            time.Time    `json:"fecha" gorm:"column:fecha;not null"`
	Descripcion      string       `json:"descripcion" gorm:"column:descripcion;type:text"`
	Valor            float64      `json:"valor" gorm:"column:valor;not null"`
	Estado           string       `json:"estado" gorm:"column:estado;size:20;default:'pendiente'"` // pendiente | pagado | parcial
	FechaVencimiento *time.Time   `json:"fecha_vencimiento" gorm:"column:fecha_vencimiento"`
	FechaPago        *time.Time   `json:"fecha_pago" gorm:"column:fecha_pago"`
	TransaccionID    *uint        `json:"transaccion_id" gorm:"column:transaccion_id"`
	Transaccion      *Transaccion `json:"transaccion" gorm:"foreignKey:TransaccionID"`
	Notas            string       `json:"notas" gorm:"column:notas;type:text"`
}

func (CuentaCobro) TableName() string { return "contab_cuentas_cobro" }

// ─── CuentaPagar (cuentas por pagar) ─────────────────────────────────────────

type CuentaPagar struct {
	gorm.Model
	EntidadID     uint         `json:"entidad_id" gorm:"column:entidad_id;index;not null"`
	Entidad       Entidad      `json:"entidad" gorm:"foreignKey:EntidadID"`
	Fecha         time.Time    `json:"fecha" gorm:"column:fecha;not null"`
	Descripcion   string       `json:"descripcion" gorm:"column:descripcion;type:text"`
	Valor         float64      `json:"valor" gorm:"column:valor;not null"`
	Vencimiento   *time.Time   `json:"vencimiento" gorm:"column:vencimiento"`
	Estado        string       `json:"estado" gorm:"column:estado;size:20;default:'pendiente'"` // pendiente | pagado | parcial
	FechaPago     *time.Time   `json:"fecha_pago" gorm:"column:fecha_pago"`
	TransaccionID *uint        `json:"transaccion_id" gorm:"column:transaccion_id"`
	Transaccion   *Transaccion `json:"transaccion" gorm:"foreignKey:TransaccionID"`
	Notas         string       `json:"notas" gorm:"column:notas;type:text"`
}

func (CuentaPagar) TableName() string { return "contab_cuentas_pagar" }

// ─── ConsolidadoMensual ──────────────────────────────────────────────────────

type ConsolidadoMensual struct {
	gorm.Model
	Anio             int     `json:"anio" gorm:"column:anio;not null"`
	Mes              int     `json:"mes" gorm:"column:mes;not null"`
	TotalIngresos    float64 `json:"total_ingresos" gorm:"column:total_ingresos;default:0"`
	TotalEgresos     float64 `json:"total_egresos" gorm:"column:total_egresos;default:0"`
	TotalRetenciones float64 `json:"total_retenciones" gorm:"column:total_retenciones;default:0"`
	Resultado        float64 `json:"resultado" gorm:"column:resultado;default:0"`
}

func (ConsolidadoMensual) TableName() string { return "contab_consolidado" }

// =============================================================================
// ─── CRUD: Cuenta ───────────────────────────────────────────────────────────
// =============================================================================

func GetAllCuentas(limit, offset int, search string) ([]Cuenta, int64, error) {
	var items []Cuenta
	var total int64
	db := app.Http.Database.DB.Model(&Cuenta{})
	if search != "" {
		db = db.Where("nombre ILIKE ? OR codigo ILIKE ?", "%"+search+"%", "%"+search+"%")
	}
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if err := db.Order("tipo ASC, nombre ASC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
		return nil, 0, err
	}
	return items, total, nil
}

func GetAllCuentasSelect() ([]Cuenta, error) {
	var items []Cuenta
	if err := app.Http.Database.DB.Where("activo = ?", true).Order("nombre ASC").Find(&items).Error; err != nil {
		return nil, err
	}
	return items, nil
}

func CreateCuenta(c *Cuenta) error {
	return app.Http.Database.DB.Create(c).Error
}

func UpdateCuenta(c *Cuenta) error {
	return app.Http.Database.DB.Model(&Cuenta{}).Where("id = ?", c.ID).Updates(map[string]interface{}{
		"codigo": c.Codigo,
		"nombre": c.Nombre,
		"tipo":   c.Tipo,
		"color":  c.Color,
		"activo": c.Activo,
	}).Error
}

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

// =============================================================================
// ─── CRUD: Entidad ──────────────────────────────────────────────────────────
// =============================================================================

func GetAllEntidades(limit, offset int, search string) ([]Entidad, int64, error) {
	var items []Entidad
	var total int64
	db := app.Http.Database.DB.Model(&Entidad{})
	if search != "" {
		db = db.Where("nombre ILIKE ? OR documento ILIKE ? OR email ILIKE ?",
			"%"+search+"%", "%"+search+"%", "%"+search+"%")
	}
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if err := db.Order("nombre ASC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
		return nil, 0, err
	}
	return items, total, nil
}

func GetAllEntidadesSelect() ([]Entidad, error) {
	var items []Entidad
	if err := app.Http.Database.DB.Where("activo = ?", true).Order("nombre ASC").Find(&items).Error; err != nil {
		return nil, err
	}
	return items, nil
}

func CreateEntidad(e *Entidad) error {
	return app.Http.Database.DB.Create(e).Error
}

func UpdateEntidad(e *Entidad) error {
	return app.Http.Database.DB.Model(&Entidad{}).Where("id = ?", e.ID).Updates(map[string]interface{}{
		"nombre":    e.Nombre,
		"tipo":      e.Tipo,
		"documento": e.Documento,
		"email":     e.Email,
		"telefono":  e.Telefono,
		"contacto":  e.Contacto,
		"notas":     e.Notas,
		"activo":    e.Activo,
	}).Error
}

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

// =============================================================================
// ─── CRUD: Transaccion ──────────────────────────────────────────────────────
// =============================================================================

func GetAllTransacciones(limit, offset int, search string, filtroTipo string, mes int, anio int) ([]Transaccion, int64, error) {
	var items []Transaccion
	var total int64
	db := app.Http.Database.DB.Model(&Transaccion{}).Preload("Cuenta").Preload("Entidad")
	if search != "" {
		db = db.Where("descripcion ILIKE ?", "%"+search+"%")
	}
	if filtroTipo != "" {
		db = db.Where("tipo = ?", filtroTipo)
	}
	if mes > 0 && anio > 0 {
		db = db.Where("EXTRACT(MONTH FROM fecha) = ? AND EXTRACT(YEAR FROM fecha) = ?", mes, anio)
	}
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if err := db.Order("fecha DESC, created_at DESC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
		return nil, 0, err
	}
	return items, total, nil
}

func CreateTransaccion(t *Transaccion) error {
	return app.Http.Database.DB.Create(t).Error
}

func UpdateTransaccion(t *Transaccion) error {
	return app.Http.Database.DB.Model(&Transaccion{}).Where("id = ?", t.ID).Updates(map[string]interface{}{
		"fecha":       t.Fecha,
		"tipo":        t.Tipo,
		"descripcion": t.Descripcion,
		"valor":       t.Valor,
		"cuenta_id":   t.CuentaID,
		"entidad_id":  t.EntidadID,
		"forma_pago":  t.FormaPago,
		"estado":      t.Estado,
		"notas":       t.Notas,
	}).Error
}

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

// =============================================================================
// ─── CRUD: CuentaCobro ──────────────────────────────────────────────────────
// =============================================================================

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

func SeedBalanceData() {
	db := app.Http.Database.DB

	parseDate := func(s string) time.Time {
		t, _ := time.Parse("2006-01-02 15:04:05", s)
		return t
	}

	getEntidad := func(nombre string) *uint {
		var e Entidad
		if err := db.Where("nombre = ?", nombre).First(&e).Error; err == nil {
			return &e.ID
		}
		e = Entidad{Nombre: nombre, Tipo: "cliente", Activo: true}
		db.Create(&e)
		return &e.ID
	}

	getCuenta := func(codigo string) *uint {
		var c Cuenta
		if err := db.Where("codigo = ?", codigo).First(&c).Error; err == nil {
			return &c.ID
		}
		return nil
	}

	// ─── FACTURAS → Transacciones (ingresos) ────────────────────────────────
	facturas := []struct {
		factura float64
		valor   float64
		fecha   string
	}{
		{54, 450000, "2026-01-01 00:00:00"},
		{55, 9000000, "2026-01-01 00:00:00"},
		{56, 119000, "2026-01-01 00:00:00"},
		{57, 330000, "2026-01-01 00:00:00"},
		{58, 1000000, "2026-01-01 00:00:00"},
		{59, 1000000, "2026-01-01 00:00:00"},
		{60, 900000, "2026-01-01 00:00:00"},
		{0, 0, "2026-01-01 00:00:00"}, // ajuste -130000
		{61, 580000, "2026-02-01 00:00:00"},
		{62, 330000, "2026-02-01 00:00:00"},
		{63, 1785000, "2026-02-01 00:00:00"},
		{64, 120000, "2026-02-01 00:00:00"},
		{65, 350000, "2026-02-01 00:00:00"},
		{66, 550000, "2026-02-01 00:00:00"},
		{67, 1300000, "2026-02-01 00:00:00"},
		{68, 270000, "2026-02-01 00:00:00"},
		{69, 32000, "2026-02-01 00:00:00"},
		{70, 3153500, "2026-02-01 00:00:00"},
		{71, 349000, "2026-03-01 00:00:00"},
		{72, 0, "2026-03-01 00:00:00"},
		{73, 1380000, "2026-03-01 00:00:00"},
		{74, 380000, "2026-03-01 00:00:00"},
		{75, 2650000, "2026-04-01 00:00:00"},
		{76, 390000, "2026-04-01 00:00:00"},
		{77, 2200000, "2026-04-01 00:00:00"},
		{78, 4400000, "2026-04-01 00:00:00"},
		{79, 142000, "2026-04-01 00:00:00"},
	}
	cuentaIng := getCuenta("ING-FAC")
	docuxer := getEntidad("DOCUXER")
	giaf := getEntidad("GIAF SAS")

	for _, f := range facturas {
		if f.factura == 0 && f.valor == 0 {
			// ajuste negativo: nota crédito
			var existing Transaccion
			if db.Where("descripcion = ?", "Ajuste/NC ene 2026").First(&existing).Error != nil {
				db.Create(&Transaccion{
					Fecha: parseDate("2026-01-01 00:00:00"),
					Tipo:  "egreso", Descripcion: "Ajuste/NC ene 2026",
					Valor: 130000, CuentaID: cuentaIng, Estado: "registrada",
				})
			}
			continue
		}
		desc := fmt.Sprintf("Factura #%.0f", f.factura)
		var existing Transaccion
		if db.Where("descripcion = ? AND fecha = ?", desc, parseDate(f.fecha)).First(&existing).Error != nil {
			eid := docuxer
			if f.factura == 56 {
				eid = giaf
			}
			db.Create(&Transaccion{
				Fecha: parseDate(f.fecha), Tipo: "ingreso",
				Descripcion: desc, Valor: f.valor,
				CuentaID: cuentaIng, EntidadID: eid, Estado: "registrada",
			})
		}
	}

	// ─── IVA → Transacciones (egresos) ──────────────────────────────────────
	ivas := []struct {
		valor   float64
		entidad string
		desc    string
	}{
		{285000, "DOCUXER", "IVA Fact #63"},
		{503500, "DOCUXER", "IVA Fact #70"},
		{19000, "GIAF SAS", "IVA Fact #56"},
		{503500, "DOCUXER", "IVA Fact #75"},
		{418000, "DOCUXER", "IVA Fact #77"},
	}
	cuentaImp := getCuenta("EGR-IMPU")
	for _, iv := range ivas {
		var existing Transaccion
		if db.Where("descripcion = ?", iv.desc).First(&existing).Error != nil {
			eid := getEntidad(iv.entidad)
			db.Create(&Transaccion{
				Fecha: parseDate("2026-01-01 00:00:00"),
				Tipo:  "egreso", Descripcion: iv.desc,
				Valor: iv.valor, CuentaID: cuentaImp,
				EntidadID: eid, Estado: "registrada",
			})
		}
	}

	// ─── RETENCION → Transacciones (egresos) ────────────────────────────────
	rets := []struct {
		valor  float64
		fecha  string
		estado string
	}{
		{195000, "2026-03-01 00:00:00", "pagado"},
		{257000, "2026-02-01 00:00:00", "pagado"},
		{431000, "2026-01-01 00:00:00", "pendiente"},
	}
	for _, r := range rets {
		desc := fmt.Sprintf("Retención %s", r.fecha[:7])
		var existing Transaccion
		if db.Where("descripcion = ?", desc).First(&existing).Error != nil {
			db.Create(&Transaccion{
				Fecha: parseDate(r.fecha),
				Tipo:  "egreso", Descripcion: desc,
				Valor: r.valor, CuentaID: cuentaImp,
				Estado: "registrada",
			})
		}
	}

	// ─── CUENTAS DE COBRO (las que te pasan a ti) → CuentasPagar ────────────
	cobros := []struct {
		entidad string
		valor   float64
		fecha   string
	}{
		{"NATALIA", 2000000, "2026-01-01 00:00:00"},
		{"FELIPE", 2000000, "2026-01-01 00:00:00"},
		{"CONTADORA", 1780000, "2026-01-01 00:00:00"},
		{"FELIPE", 2300000, "2026-02-01 00:00:00"},
		{"NATALIA", 2000000, "2026-02-01 00:00:00"},
		{"FELIPE", 2300000, "2026-03-01 00:00:00"},
		{"NATALIA", 2000000, "2026-03-01 00:00:00"},
		{"FELIPE", 520000, "2026-04-01 00:00:00"},
		{"ANDREMER", 80000, "2026-04-01 00:00:00"},
		{"NATALIA", 2000000, "2026-04-01 00:00:00"},
		// FAC POR PAGAR
		{"TECZONE", 2687849, "2026-01-01 00:00:00"},
	}
	for _, cb := range cobros {
		eid := getEntidad(cb.entidad)
		desc := fmt.Sprintf("%s %s", cb.entidad, cb.fecha[:7])
		var existing CuentaPagar
		if db.Where("descripcion = ?", desc).First(&existing).Error != nil {
			df := parseDate(cb.fecha)
			db.Create(&CuentaPagar{
				EntidadID: *eid, Fecha: df,
				Descripcion: desc, Valor: cb.valor,
				Estado: "pendiente",
			})
		}
	}

	// ─── CONSOLIDADO POR MES ───────────────────────────────────────────────
	consols := []struct {
		mes              int
		ing, egre, resul float64
	}{
		{1, 12669000, 8467849, 4201151},
		{2, 8470500, 4300000, 4170500},
		{3, 2109000, 4300000, -2191000},
		{4, 9782000, 2600000, 7182000},
	}
	for _, cs := range consols {
		var existing ConsolidadoMensual
		if db.Where("anio = 2026 AND mes = ?", cs.mes).First(&existing).Error != nil {
			db.Create(&ConsolidadoMensual{
				Anio: 2026, Mes: cs.mes,
				TotalIngresos: cs.ing, TotalEgresos: cs.egre,
				Resultado: cs.resul,
			})
		}
	}

	log.Println("[SEED] Balance data imported from BALANCE.numbers")
}

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

func CreateCuentaCobro(cc *CuentaCobro) error {
	return app.Http.Database.DB.Create(cc).Error
}

func UpdateCuentaCobro(cc *CuentaCobro) error {
	return app.Http.Database.DB.Model(&CuentaCobro{}).Where("id = ?", cc.ID).Updates(map[string]interface{}{
		"cliente_id":        cc.ClienteID,
		"estado":            cc.Estado,
		"fecha_vencimiento": cc.FechaVencimiento,
		"fecha_pago":        cc.FechaPago,
		"transaccion_id":    cc.TransaccionID,
		"notas":             cc.Notas,
	}).Error
}

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

// =============================================================================
// ─── CRUD: CuentaPagar ──────────────────────────────────────────────────────
// =============================================================================

func GetAllCuentasPagar(limit, offset int, search string, estado string) ([]CuentaPagar, int64, error) {
	var items []CuentaPagar
	var total int64
	db := app.Http.Database.DB.Model(&CuentaPagar{}).Preload("Entidad").Preload("Transaccion")
	if search != "" {
		db = db.Joins("JOIN contab_entidades ON contab_entidades.id = contab_cuentas_pagar.entidad_id").
			Where("contab_entidades.nombre ILIKE ? OR contab_cuentas_pagar.descripcion ILIKE ?",
				"%"+search+"%", "%"+search+"%")
	}
	if estado != "" {
		db = db.Where("contab_cuentas_pagar.estado = ?", estado)
	}
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if err := db.Order("contab_cuentas_pagar.fecha DESC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
		return nil, 0, err
	}
	return items, total, nil
}

func CreateCuentaPagar(cp *CuentaPagar) error {
	return app.Http.Database.DB.Create(cp).Error
}

func UpdateCuentaPagar(cp *CuentaPagar) error {
	return app.Http.Database.DB.Model(&CuentaPagar{}).Where("id = ?", cp.ID).Updates(map[string]interface{}{
		"entidad_id":     cp.EntidadID,
		"fecha":          cp.Fecha,
		"descripcion":    cp.Descripcion,
		"valor":          cp.Valor,
		"vencimiento":    cp.Vencimiento,
		"estado":         cp.Estado,
		"fecha_pago":     cp.FechaPago,
		"transaccion_id": cp.TransaccionID,
		"notas":          cp.Notas,
	}).Error
}

func MarcarCuentaPagarPagada(id uint, fechaPago time.Time) error {
	return app.Http.Database.DB.Model(&CuentaPagar{}).Where("id = ?", id).Updates(map[string]interface{}{
		"estado":     "pagado",
		"fecha_pago": fechaPago,
	}).Error
}

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

// =============================================================================
// ─── Consolidado ────────────────────────────────────────────────────────────
// =============================================================================

func GetConsolidadoMensual(mes, anio int) (*ConsolidadoMensual, error) {
	var c ConsolidadoMensual
	err := app.Http.Database.DB.Where("mes = ? AND anio = ?", mes, anio).First(&c).Error
	if err != nil {
		return nil, err
	}
	return &c, nil
}

func CalcularYGuardarConsolidado(mes, anio int) (*ConsolidadoMensual, error) {
	type SumRow struct {
		Total float64
	}
	var ingresos SumRow
	var egresos SumRow

	app.Http.Database.DB.Model(&Transaccion{}).
		Select("COALESCE(SUM(valor),0) as total").
		Where("tipo = ? AND EXTRACT(MONTH FROM fecha) = ? AND EXTRACT(YEAR FROM fecha) = ?", "ingreso", mes, anio).
		Scan(&ingresos)

	app.Http.Database.DB.Model(&Transaccion{}).
		Select("COALESCE(SUM(valor),0) as total").
		Where("tipo = ? AND EXTRACT(MONTH FROM fecha) = ? AND EXTRACT(YEAR FROM fecha) = ?", "egreso", mes, anio).
		Scan(&egresos)

	resultado := ingresos.Total - egresos.Total

	c := &ConsolidadoMensual{
		Anio:             anio,
		Mes:              mes,
		TotalIngresos:    ingresos.Total,
		TotalEgresos:     egresos.Total,
		TotalRetenciones: 0,
		Resultado:        resultado,
	}

	var existing ConsolidadoMensual
	err := app.Http.Database.DB.Where("mes = ? AND anio = ?", mes, anio).First(&existing).Error
	if err == nil {
		c.ID = existing.ID
		app.Http.Database.DB.Model(&ConsolidadoMensual{}).Where("id = ?", c.ID).Updates(map[string]interface{}{
			"total_ingresos":    c.TotalIngresos,
			"total_egresos":     c.TotalEgresos,
			"total_retenciones": c.TotalRetenciones,
			"resultado":         c.Resultado,
		})
	} else {
		app.Http.Database.DB.Create(c)
	}

	return c, nil
}

func ListConsolidados(anio int) ([]ConsolidadoMensual, error) {
	var items []ConsolidadoMensual
	db := app.Http.Database.DB.Model(&ConsolidadoMensual{}).Order("anio DESC, mes DESC")
	if anio > 0 {
		db = db.Where("anio = ?", anio)
	}
	if err := db.Find(&items).Error; err != nil {
		return nil, err
	}
	return items, nil
}

// ─── Datos para dashboard ────────────────────────────────────────────────────

type DashboardData struct {
	Mes               int           `json:"mes"`
	Anio              int           `json:"anio"`
	TotalIngresos     float64       `json:"total_ingresos"`
	TotalEgresos      float64       `json:"total_egresos"`
	Resultado         float64       `json:"resultado"`
	CantTransacciones int64         `json:"cant_transacciones"`
	PendientesCobro   float64       `json:"pendientes_cobro"`
	PendientesPago    float64       `json:"pendientes_pago"`
	Transacciones     []Transaccion `json:"transacciones"`
}

func GetDashboardData(mes, anio int) (*DashboardData, error) {
	d := &DashboardData{Mes: mes, Anio: anio}

	app.Http.Database.DB.Model(&Transaccion{}).
		Select("COALESCE(SUM(valor),0) as total").
		Where("tipo = ? AND EXTRACT(MONTH FROM fecha) = ? AND EXTRACT(YEAR FROM fecha) = ?", "ingreso", mes, anio).
		Scan(&d.TotalIngresos)

	app.Http.Database.DB.Model(&Transaccion{}).
		Select("COALESCE(SUM(valor),0) as total").
		Where("tipo = ? AND EXTRACT(MONTH FROM fecha) = ? AND EXTRACT(YEAR FROM fecha) = ?", "egreso", mes, anio).
		Scan(&d.TotalEgresos)

	d.Resultado = d.TotalIngresos - d.TotalEgresos

	app.Http.Database.DB.Model(&Transaccion{}).
		Where("EXTRACT(MONTH FROM fecha) = ? AND EXTRACT(YEAR FROM fecha) = ?", mes, anio).
		Count(&d.CantTransacciones)

	app.Http.Database.DB.Model(&CuentaCobro{}).
		Select("COALESCE(SUM(valor),0) as total").
		Where("estado = ?", "pendiente").
		Scan(&d.PendientesCobro)

	app.Http.Database.DB.Model(&CuentaPagar{}).
		Select("COALESCE(SUM(valor),0) as total").
		Where("estado = ?", "pendiente").
		Scan(&d.PendientesPago)

	app.Http.Database.DB.Model(&Transaccion{}).
		Preload("Cuenta").Preload("Entidad").
		Where("EXTRACT(MONTH FROM fecha) = ? AND EXTRACT(YEAR FROM fecha) = ?", mes, anio).
		Order("fecha DESC").
		Limit(10).
		Find(&d.Transacciones)

	return d, nil
}

func SeedContabilidad() {
	cuentas := []Cuenta{
		{Codigo: "ING-FAC", Nombre: "Facturación", Tipo: "ingreso", Color: "#22c55e"},
		{Codigo: "ING-OTR", Nombre: "Otros ingresos", Tipo: "ingreso", Color: "#16a34a"},
		{Codigo: "EGR-HOS", Nombre: "Hosting/Servidores", Tipo: "egreso", Color: "#ef4444"},
		{Codigo: "EGR-DOM", Nombre: "Dominios", Tipo: "egreso", Color: "#dc2626"},
		{Codigo: "EGR-SRV", Nombre: "Servicios", Tipo: "egreso", Color: "#f97316"},
		{Codigo: "EGR-GRAL", Nombre: "Gastos generales", Tipo: "egreso", Color: "#eab308"},
		{Codigo: "EGR-NOM", Nombre: "Nómina", Tipo: "egreso", Color: "#a855f7"},
		{Codigo: "EGR-IMPU", Nombre: "Impuestos", Tipo: "egreso", Color: "#6366f1"},
		{Codigo: "EGR-MKT", Nombre: "Marketing", Tipo: "egreso", Color: "#ec4899"},
	}
	for _, c := range cuentas {
		var existing Cuenta
		if app.Http.Database.DB.Where("codigo = ?", c.Codigo).First(&existing).Error != nil {
			app.Http.Database.DB.Create(&c)
		}
	}

	entidades := []Entidad{
		{Nombre: "DOCUXER", Tipo: "cliente"},
		{Nombre: "GIAF SAS", Tipo: "cliente"},
		{Nombre: "TECZONE", Tipo: "proveedor"},
		{Nombre: "FELIPE", Tipo: "proveedor"},
		{Nombre: "NATALIA", Tipo: "proveedor"},
		{Nombre: "CONTADORA", Tipo: "proveedor"},
		{Nombre: "ANDREMER", Tipo: "proveedor"},
	}
	for _, e := range entidades {
		var existing Entidad
		if app.Http.Database.DB.Where("nombre = ?", e.Nombre).First(&existing).Error != nil {
			app.Http.Database.DB.Create(&e)
		}
	}
}
