package repositories

import (
	"context"
	"daemonService/internal/models/obtencionCodigos"
	"database/sql"
	"fmt"
	"time"
)

type EmpresaRepository struct {
	Model obtencionCodigos.CuisServiceModel
}

// instanciamos empresaRepository
func NewEmpresaRepository(
	model obtencionCodigos.CuisServiceModel,
) *EmpresaRepository {
	return &EmpresaRepository{Model: model}
}

// obtiene todas las empresas con sus CUIS
func (s *EmpresaRepository) GetEmpresasConCuisMinimal(ctx context.Context) ([]obtencionCodigos.EmpresaConCuis, error) {
	const query = `
   SELECT
     -- columnas de registroEmpresa
     re.id, re.codigo_ambiente, re.codigo_modalidad, re.codigo_punto_venta,
     re.codigo_sistema, re.codigo_sucursal, re.nit,
     re.fecha_creacion, re.fecha_actualizacion, re.token_key, re.token_value,
     re.nombre_archivo_clave_privada, re.nombre_archivo_certificado,
     c.id, c.cuis, c.fecha_vigencia
   FROM registroEmpresa re
   LEFT JOIN cuis c ON c.registro_empresa_id = re.id
   ORDER BY re.id;
   `

	rows, err := s.Model.DB.QueryContext(ctx, query)
	if err != nil {
		return nil, fmt.Errorf("consulta empresas con cuis minimal: %w", err)
	}
	defer rows.Close()

	// Mapa temporal para agrupar por empresa.ID
	empresasMap := make(map[int]*obtencionCodigos.EmpresaConCuis)

	for rows.Next() {
		// Variables temporales de escaneo
		var (
			id                        int
			codigoAmbiente            int
			codigoModalidad           int
			codigoPuntoVenta          int
			codigoSistema             string
			codigoSucursal            int
			nit                       string
			fechaCreacion             time.Time
			fechaActualizacion        time.Time
			tokenKey                  string
			tokenValue                string
			nombreArchivoClavePrivada string
			nombreArchivoCertificado  string

			idCuis        sql.NullInt64
			cuis          sql.NullString
			fechaVigencia sql.NullTime
		)

		// Leer la fila
		if err := rows.Scan(
			&id, &codigoAmbiente, &codigoModalidad, &codigoPuntoVenta,
			&codigoSistema, &codigoSucursal, &nit,
			&fechaCreacion, &fechaActualizacion, &tokenKey, &tokenValue,
			&nombreArchivoClavePrivada, &nombreArchivoCertificado,
			&idCuis, &cuis, &fechaVigencia,
		); err != nil {
			return nil, fmt.Errorf("scan fila: %w", err)
		}

		// ¿Ya existe la empresa en el mapa?
		ent, ok := empresasMap[id]
		if !ok {
			// Si no existe, la creamos y rellenamos datos de registroEmpresa
			ent = &obtencionCodigos.EmpresaConCuis{
				RegistroEmpresa: obtencionCodigos.RegistroEmpresa{
					ID:                        id,
					CodigoAmbiente:            codigoAmbiente,
					CodigoModalidad:           codigoModalidad,
					CodigoPuntoVenta:          codigoPuntoVenta,
					CodigoSistema:             codigoSistema,
					CodigoSucursal:            codigoSucursal,
					Nit:                       nit,
					FechaCreacion:             fechaCreacion,
					FechaActualizacion:        fechaActualizacion,
					TokenKey:                  tokenKey,
					TokenValue:                tokenValue,
					NombreArchivoClavePrivada: nombreArchivoClavePrivada,
					NombreArchivoCertificado:  nombreArchivoCertificado,
				},
				Cuis: make([]obtencionCodigos.CuisMinimal, 0, 1),
			}
			empresasMap[id] = ent
		}

		// Si hay un CUIS válido, lo añadimos al slice
		if idCuis.Valid && cuis.Valid && fechaVigencia.Valid {
			ent.Cuis = append(ent.Cuis, obtencionCodigos.CuisMinimal{
				Cuis_id:       idCuis.Int64,
				Cuis:          cuis.String,
				FechaVigencia: fechaVigencia.Time,
			})
		}
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iteración filas: %w", err)
	}

	// Convertimos el mapa a slice ordenado por aparición
	resp := make([]obtencionCodigos.EmpresaConCuis, 0, len(empresasMap))
	for _, ent := range empresasMap {
		resp = append(resp, *ent)
	}
	return resp, nil
}
