package obtencionCodigo

//
//import (
//	"context"
//	"daemonService/internal/handlers"
//	"daemonService/internal/models"
//	svc "daemonService/internal/models"
//	"daemonService/internal/models/obtencionCodigos"
//	"daemonService/internal/repositories"
//	"daemonService/internal/services/obtencionCodigo"
//	"daemonService/internal/services/procesar"
//	"daemonService/internal/services/sincronizacionDatos"
//	"flag"
//	"fmt"
//	"github.com/robfig/cron/v3"
//	"log"
//	"net/http"
//	"os"
//	"os/signal"
//	"syscall"
//	"time"
//
//	"daemonService/internal/api"
//	"daemonService/internal/config"
//	"daemonService/internal/database"
//	"daemonService/internal/notifications"
//	"daemonService/internal/services"
//)
//
//func main() {
//	configFile := flag.String("config", "configs/config.yaml", "Ruta al archivo de configuración")
//	runOnce := flag.Bool("run-once", false, "Ejecutar servicios una vez y salir")
//	serviceName := flag.String("service", "", "Nombre del servicio específico a ejecutar")
//	flag.Parse()
//
//	// Cargar configuración
//	cfg, err := config.LoadConfig(*configFile)
//	if err != nil {
//		log.Fatalf("Error al cargar configuración: %v", err)
//	}
//
//	// Inicializar la base de datos
//	db, err := database.InitDB(*cfg)
//	if err != nil {
//		log.Fatalf("Error al inicializar la base de datos: %v", err)
//	}
//	defer db.Close()
//
//	// Crear sistema de notificaciones
//	notifier := notifications.CreateNotificationSender(cfg.Notifications.Enabled, cfg.Notifications.Method, cfg.Notifications.Config)
//	if notifier != nil {
//		log.Printf("Sistema de notificaciones iniciado: %s", cfg.Notifications.Method)
//	}
//
//	// Crear servicios a partir de la configuración
//	//var cuisServices []models.CuisService
//	var servicesList []models.SoapService
//	var servicesList2 []obtencionCodigos.CuisService
//	for _, svcCfg := range cfg.Services {
//		if !svcCfg.Enabled {
//			continue
//		}
//
//		// Crear el logger para el servicio
//		serviceLogger := log.New(log.Writer(), fmt.Sprintf("[%s] ", svcCfg.Name), log.LstdFlags)
//
//		log.Println(cfg.SOAP.FACTURA_SINCRONIZACION.Retries)
//		baseSvc := svc.ServiceModel{
//			Name:               svcCfg.Name,
//			Enabled:            svcCfg.Enabled,
//			Concurrency:        svcCfg.Concurrency,
//			DB:                 db,
//			SOAPEndpoint:       cfg.SOAP.FACTURA_SINCRONIZACION.Endpoint,
//			SOAPTimeout:        time.Duration(cfg.SOAP.FACTURA_SINCRONIZACION.Timeout) * time.Second,
//			SOAPRetries:        cfg.SOAP.FACTURA_SINCRONIZACION.Retries,
//			NotificationSender: notifier,
//			APIKey:             cfg.SOAP.APIKey,
//			TagNames:           "",
//			QueryInsert:        "",
//			MsgCustomResponse:  "",
//		}
//
//		cuisServiceModel := obtencionCodigos.CuisServiceModel{
//			Name:               svcCfg.Name,
//			Enabled:            svcCfg.Enabled,
//			Concurrency:        svcCfg.Concurrency,
//			DB:                 db,
//			SOAPEndpoint:       cfg.SOAP.FACTURA_CODIGO.Endpoint,
//			SOAPTimeout:        time.Duration(cfg.SOAP.FACTURA_CODIGO.Timeout) * time.Second,
//			SOAPRetries:        cfg.SOAP.FACTURA_CODIGO.Retries,
//			NotificationSender: notifier,
//			APIKey:             cfg.SOAP.APIKey,
//			TagNames:           "",
//			QueryInsert:        "",
//			MsgCustomResponse:  "",
//		}
//
//		//registrar-empresa solo para registrar empresa
//		cuisServiceModel.TagNames = "cuis"
//		cuisServiceModel.QueryInsert = "INSERT INTO registroEmpresa (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//		cuisServiceModel.MsgCustomResponse = "Registrar Empresa"
//
//		procesarRegistro := procesar.NewProcesarRegistro(cuisServiceModel)
//		empresaRepository := repositories.NewEmpresaRepository(cuisServiceModel)
//		cuisService := services.NewCuisService(cuisServiceModel, serviceLogger)
//		cuisRepository := repositories.NewCuisRepository(baseSvc, cuisService)
//		cronHandler := handlers.NewCronHandler(cuisService, empresaRepository, cuisRepository, procesarRegistro)
//		apiHandler := handlers.NewApiHandler(cuisService, cuisRepository, procesarRegistro)
//
//		// Llamar a NewObtencionCodigoService correctamente
//		obtencionCodigoSvc := obtencionCodigo.NewObtencionCodigoService(
//			cuisServiceModel,
//			cuisService,
//			cronHandler,
//			apiHandler,
//		)
//
//		switch svcCfg.Name {
//		case "registrar-empresa":
//			servicesList2 = append(servicesList2, obtencionCodigoSvc)
//			break
//		case "leyendas_factura":
//			baseSvc.TagNames = "sincronizarListaLeyendasFactura"
//			baseSvc.QueryInsert = "INSERT INTO leyendas_factura (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//			baseSvc.MsgCustomResponse = "Listado Leyendas de Facturas"
//			servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
//				ServiceModel: baseSvc,
//			})
//		case "producto-servicio":
//			baseSvc.TagNames = "sincronizarListaProductosServicios"
//			baseSvc.QueryInsert = "INSERT INTO productos_servicios (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//			baseSvc.MsgCustomResponse = "Listado Producto Servicio"
//			servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
//				ServiceModel: baseSvc,
//			})
//		case "tipo_documento_identidad":
//			baseSvc.TagNames = "sincronizarParametricaTipoDocumentoIdentidad"
//			baseSvc.QueryInsert = "INSERT INTO tipo_documento_identidad (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//			baseSvc.MsgCustomResponse = "Listado tipos de documento de identidad"
//			servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
//				ServiceModel: baseSvc,
//			})
//		case "tipo_documento_sector":
//			baseSvc.TagNames = "sincronizarParametricaTipoDocumentoSector"
//			baseSvc.QueryInsert = "INSERT INTO tipo_documento_sector (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//			baseSvc.MsgCustomResponse = "Listado tipos de documento de identidad"
//			servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
//				ServiceModel: baseSvc,
//			})
//		case "tipo_metodo_pago":
//			baseSvc.TagNames = "sincronizarParametricaTipoMetodoPago"
//			baseSvc.QueryInsert = "INSERT INTO tipo_metodo_pago (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//			baseSvc.MsgCustomResponse = "Listado tipos metodo de pago"
//			servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
//				ServiceModel: baseSvc,
//			})
//		case "tipo_moneda":
//			baseSvc.TagNames = "sincronizarParametricaTipoMoneda"
//			baseSvc.QueryInsert = "INSERT INTO tipo_moneda (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//			baseSvc.MsgCustomResponse = "Listado tipos de moneda"
//			servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
//				ServiceModel: baseSvc,
//			})
//		case "tipo_punto_venta":
//			baseSvc.TagNames = "sincronizarParametricaTipoPuntoVenta"
//			baseSvc.QueryInsert = "INSERT INTO tipo_punto_venta (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//			baseSvc.MsgCustomResponse = "Listado tipos de punto de venta"
//			servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
//				ServiceModel: baseSvc,
//			})
//		case "tipo_unidad_medida":
//			baseSvc.TagNames = "sincronizarParametricaUnidadMedida"
//			baseSvc.QueryInsert = "INSERT INTO tipo_unidad_medida (codigo, reqSoap, respSoap, reqJson, respJson, cuis_id, fecha_creacion) VALUES ($1, $2, $3, $4, $5, $6, NOW() AT TIME ZONE 'America/La_Paz') ON CONFLICT (codigo, cuis_id) DO UPDATE SET reqSoap = EXCLUDED.reqSoap, respSoap = EXCLUDED.respSoap, reqJson = EXCLUDED.reqJson, respJson = EXCLUDED.respJson, cuis_id = EXCLUDED.cuis_id, fecha_actualizacion = NOW() AT TIME ZONE 'America/La_Paz';"
//			baseSvc.MsgCustomResponse = "Listado tipos de unidad de medida"
//			servicesList = append(servicesList, &sincronizacionDatos.SincronizacionDatosService{
//				ServiceModel: baseSvc,
//			})
//		default:
//			log.Printf("Servicio desconocido: %s", svcCfg.Name)
//		}
//	}
//
//	// Si se especifica un servicio específico, filtrar la lista.
//	if *serviceName != "" {
//		var filtered []models.SoapService
//		for _, s := range servicesList {
//			if s.GetName() == *serviceName {
//				filtered = append(filtered, s)
//				break
//			}
//		}
//		if len(filtered) == 0 {
//			log.Fatalf("No se encontró el servicio: %s", *serviceName)
//		}
//		servicesList = filtered
//		log.Printf("Ejecutando solo el servicio: %s", *serviceName)
//	}
//
//	// Crear contexto con cancelación para manejar señales de terminación.
//	ctx, cancel := context.WithCancel(context.Background())
//	defer cancel()
//
//	// Canal para capturar señales del sistema.
//	sigChan := make(chan os.Signal, 1)
//	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
//
//	// Iniciar servidor HTTP si se configura puerto para API.
//	var httpServer *http.Server
//	if cfg.API.Port > 0 {
//		httpServer = api.StartAPIServer(cfg.API.Port, servicesList, servicesList2, false)
//	}
//
//	// Goroutine para manejar señales.
//	go func() {
//		sig := <-sigChan
//		log.Printf("Recibida señal: %v. Cerrando...", sig)
//		if notifier != nil {
//			notifier.SendNotification("Servicio detenido", fmt.Sprintf("El servicio fue detenido por la señal: %v", sig))
//		}
//		cancel()
//		if httpServer != nil {
//			log.Println("Cerrando servidor HTTP...")
//			shutdownCtx, cancelServer := context.WithTimeout(context.Background(), 10*time.Second)
//			defer cancelServer()
//			if err := httpServer.Shutdown(shutdownCtx); err != nil {
//				log.Printf("Error al cerrar servidor HTTP: %v", err)
//			}
//		}
//	}()
//
//	// Si se debe ejecutar solo una vez.
//	if *runOnce {
//		errors := services.RunAllServices(ctx, servicesList, false)
//		if len(errors) > 0 {
//			for _, e := range errors {
//				log.Printf("Error: %v", e)
//			}
//			os.Exit(1)
//		}
//		return
//	}
//
//	// Configurar primer cron
//	c := cron.New(cron.WithSeconds())
//	_, err = c.AddFunc(cfg.Schedule.FACTURA_SINCRONIZACION.Cron, func() {
//		log.Println("Iniciando ejecución programada de servicios")
//		execCtx, execCancel := context.WithCancel(ctx)
//		defer execCancel()
//
//		errors := services.RunAllServices(execCtx, servicesList, true)
//		if len(errors) > 0 {
//			errMsg := "Errores durante la ejecución programada:"
//			for _, err := range errors {
//				errMsg += "\n- " + err.Error()
//			}
//			if notifier != nil {
//				notifier.SendNotification("Errores en ejecución programada", errMsg)
//			}
//			log.Println(errMsg)
//		} else {
//			log.Println("Ejecución programada completada exitosamente")
//		}
//	})
//
//	if err != nil {
//		log.Fatalf("Error al programar tareas: %v", err)
//	}
//
//	// Configurar segundo cron
//	cronGetCode := cron.New(cron.WithSeconds())
//	_, err = cronGetCode.AddFunc(cfg.Schedule.FACTURA_CODIGO.Cron, func() {
//		log.Println("Iniciando ejecución programada para Obtener Codigos")
//		execCtx, cancel := context.WithCancel(context.Background())
//		defer cancel()
//		//execCtx, execCancel := context.WithCancel(ctx)
//		//defer execCancel()
//
//		errors := services.RunAllGetCodeServices(execCtx, servicesList2, true)
//		if len(errors) > 0 {
//			errMsg := "Errores durante la ejecución programada Obtener Codigos:"
//			for _, err := range errors {
//				errMsg += "\n- " + err.Error()
//			}
//			if notifier != nil {
//				notifier.SendNotification("Errores en ejecución programada Obtener Codigos", errMsg)
//			}
//			log.Println(errMsg)
//		} else {
//			log.Println("Ejecución programada completada exitosamente Obtener Codigos")
//		}
//	})
//
//	if err != nil {
//		log.Fatalf("Error al programar tareas Obtener Codigos: %v", err)
//	}
//
//	// Iniciar ambos cron
//	c.Start()
//	cronGetCode.Start()
//
//	log.Printf("Demonio de servicios iniciado. Programación: %s", cfg.Schedule.FACTURA_SINCRONIZACION.Cron)
//	log.Printf("Demonio de obtención de códigos iniciado. Programación: %s", cfg.Schedule.FACTURA_CODIGO.Cron)
//
//	if notifier != nil {
//		notifier.SendNotification("Servicios iniciados",
//			fmt.Sprintf("Los servicios SOAP han sido iniciados con programación: %s", cfg.Schedule.FACTURA_SINCRONIZACION.Cron))
//	}
//
//	// Esperar a que el contexto termine y luego detener ambos cron
//	<-ctx.Done()
//	c.Stop()
//	cronGetCode.Stop()
//	log.Println("Demonios detenidos correctamente")
//}

//package obtencionCodigo

//
//import (
//	"context"
//	"daemonService/internal/services/procesar"
//	"database/sql"
//	"encoding/json"
//	"errors"
//	"fmt"
//	"log"
//	"net/http"
//	"strconv"
//	"time"
//
//	"daemonService/internal/models/obtencionCodigos"
//	"daemonService/internal/models/obtencionCodigos/request"
//	"daemonService/internal/models/obtencionCodigos/response"
//)
//
//// Constantes para la configuración general
//const (
//	maxBodySize        = 1 * 1024 * 1024 // 1MB
//	defaultTimeZone    = "America/La_Paz"
//	logServiceStart    = "Iniciando servicio %s"
//	logServiceEnd      = "Finalizado servicio %s"
//	logErrorProcessing = "Error procesando registro %s: %v"
//)
//
//// Errores comunes
//var (
//	ErrAllFieldsRequired  = errors.New("todos los campos son requeridos")
//	ErrUnexpectedRespType = errors.New("tipo de respuesta inesperado")
//)
//
//// mapea toda la tabla registroEmpresa
//type RegistroEmpresa struct {
//	ID                 int       `sql:"id"`
//	CodigoAmbiente     int       `sql:"codigo_ambiente"`
//	CodigoModalidad    int       `sql:"codigo_modalidad"`
//	CodigoPuntoVenta   int       `sql:"codigo_punto_venta"`
//	CodigoSistema      string    `sql:"codigo_sistema"`
//	CodigoSucursal     int       `sql:"codigo_sucursal"`
//	Nit                string    `sql:"nit"`
//	FechaCreacion      time.Time `sql:"fecha_creacion"`
//	FechaActualizacion time.Time `sql:"fecha_actualizacion"`
//}
//
//// solo tiene los dos campos que quieres de la tabla cuis
//type CuisMinimal struct {
//	Cuis_id       int64     `sql:"id"`
//	Cuis          string    `sql:"cuis"`
//	FechaVigencia time.Time `sql:"fecha_vigencia"`
//}
//
//// EmpresaConCuis agrupa una empresa con sus cuis mínimos
//type EmpresaConCuis struct {
//	RegistroEmpresa
//	Cuis []CuisMinimal
//}
//
//type ObtencionCodigoService struct {
//	obtencionCodigos.CuisServiceModel
//	procesar.Procesar
//	Logger *log.Logger
//}
//
//// retorna el nombre del servicio
//func (s *ObtencionCodigoService) GetName() string {
//	return s.Name
//}
//
//// registra un mensaje con el prefijo del servicio
//func (s *ObtencionCodigoService) logMessage(format string, v ...interface{}) {
//	if s.Logger != nil {
//		s.Logger.Printf(format, v...)
//	}
//}
//
//// registra un error y devuelve el mismo error
//func (s *ObtencionCodigoService) logError(format string, err error, v ...interface{}) error {
//	args := append([]interface{}{err}, v...)
//	if s.Logger != nil {
//		s.Logger.Printf(format, args...)
//	}
//	return fmt.Errorf(format, args...)
//}
//
//// maneja la obtención de códigos CUIS
//func (s *ObtencionCodigoService) ExecuteGetCode(dbCtx context.Context, w http.ResponseWriter, req *http.Request, isCron bool) (interface{}, error) {
//	s.logMessage(logServiceStart, s.Name)
//	defer s.logMessage(logServiceEnd, s.Name)
//
//	var respCuis interface{}
//	var err error
//
//	if isCron {
//		respCuis, err = s.processCronMode(dbCtx)
//	} else {
//		respCuis, err = s.processAPIMode(dbCtx, w, req)
//	}
//
//	if err != nil {
//		return nil, err
//	}
//	return respCuis, nil
//}
//
//// procesa la ejecución en modo cron
//func (s *ObtencionCodigoService) processCronMode(dbCtx context.Context) (interface{}, error) {
//	empresasConCuis, err := s.GetEmpresasConCuisMinimal(dbCtx)
//	if err != nil {
//		return nil, s.logError("Error al obtener empresas con CUIS: %v", err)
//	}
//
//	var lastResponse interface{}
//	for _, ec := range empresasConCuis {
//		s.logMessage("Procesando empresa ID: %d", ec.ID)
//
//		if len(ec.Cuis) == 0 {
//			s.logMessage("Empresa ID %d sin CUIS registrados", ec.ID)
//			continue
//		}
//
//		for _, c := range ec.Cuis {
//			s.logMessage("Procesando CUIS ID: %d", c.Cuis_id)
//
//			cuisRequest := s.buildCuisRequestFromEmpresa(ec)
//			respCuis, err := s.CodigoProcesarRegistro(&s.CuisServiceModel, cuisRequest, 0)
//
//			if err != nil {
//				s.logError(logErrorProcessing, err, cuisRequest.CodigoSistema)
//				continue
//			}
//
//			if err := s.actualizarRegistro(dbCtx, ec.ID, c.Cuis_id, cuisRequest, respCuis); err != nil {
//				s.logError("Error actualizando registro: %v", err)
//				continue
//			}
//
//			lastResponse = respCuis
//		}
//	}
//
//	return lastResponse, nil
//}
//
//// procesa la ejecución en modo API
//func (s *ObtencionCodigoService) processAPIMode(dbCtx context.Context, w http.ResponseWriter, req *http.Request) (interface{}, error) {
//	cuisRequest, err := s.parseCuisRequest(w, req)
//	if err != nil {
//		return nil, err
//	}
//
//	if err := s.validateCuisRequest(cuisRequest); err != nil {
//		return nil, s.logError("Datos inválidos: %v", err)
//	}
//
//	respCuis, err := s.CodigoProcesarRegistro(&s.CuisServiceModel, cuisRequest, 0)
//	if err != nil {
//		return nil, s.logError(logErrorProcessing, err, cuisRequest.CodigoSistema)
//	}
//
//	if err := s.crearNuevoRegistro(dbCtx, cuisRequest, respCuis); err != nil {
//		return nil, s.logError("Error creando nuevo registro: %v", err)
//	}
//
//	return respCuis, nil
//}
//
//// parsea la solicitud de CUIS desde el body del request
//func (s *ObtencionCodigoService) parseCuisRequest(w http.ResponseWriter, req *http.Request) (request.SolicitudCuis, error) {
//	var cuisRequest request.SolicitudCuis
//
//	// Limitar el tamaño del body para prevenir ataques DoS
//	req.Body = http.MaxBytesReader(w, req.Body, maxBodySize)
//
//	decoder := json.NewDecoder(req.Body)
//	decoder.DisallowUnknownFields() // Rechazar campos desconocidos
//
//	if err := decoder.Decode(&cuisRequest); err != nil {
//		return cuisRequest, s.logError("Error al decodificar JSON: %v", err)
//	}
//
//	return cuisRequest, nil
//}
//
//// valida los datos de la solicitud CUIS
//func (s *ObtencionCodigoService) validateCuisRequest(request request.SolicitudCuis) error {
//	if request.CodigoAmbiente == "" ||
//		request.CodigoModalidad == "" ||
//		request.CodigoPuntoVenta == "" ||
//		request.CodigoSistema == "" ||
//		request.CodigoSucursal == "" ||
//		request.Nit == "" {
//		return ErrAllFieldsRequired
//	}
//	return nil
//}
//
//// crea una solicitud CUIS a partir de datos de empresa
//func (s *ObtencionCodigoService) buildCuisRequestFromEmpresa(ec EmpresaConCuis) request.SolicitudCuis {
//	return request.SolicitudCuis{
//		CodigoAmbiente:   strconv.Itoa(ec.CodigoAmbiente),
//		CodigoModalidad:  strconv.Itoa(ec.CodigoModalidad),
//		CodigoPuntoVenta: strconv.Itoa(ec.CodigoPuntoVenta),
//		CodigoSistema:    ec.CodigoSistema,
//		CodigoSucursal:   strconv.Itoa(ec.CodigoSucursal),
//		Nit:              ec.Nit,
//	}
//}
//
//// obtiene todas las empresas con sus CUIS
//func (s *ObtencionCodigoService) GetEmpresasConCuisMinimal(ctx context.Context) ([]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,
//    -- columnas específicas de cuis
//    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.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]*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
//
//			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,
//			&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 = &EmpresaConCuis{
//				RegistroEmpresa: RegistroEmpresa{
//					ID:                 id,
//					CodigoAmbiente:     codigoAmbiente,
//					CodigoModalidad:    codigoModalidad,
//					CodigoPuntoVenta:   codigoPuntoVenta,
//					CodigoSistema:      codigoSistema,
//					CodigoSucursal:     codigoSucursal,
//					Nit:                nit,
//					FechaCreacion:      fechaCreacion,
//					FechaActualizacion: fechaActualizacion,
//				},
//				Cuis: make([]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, 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([]EmpresaConCuis, 0, len(empresasMap))
//	for _, ent := range empresasMap {
//		resp = append(resp, *ent)
//	}
//	return resp, nil
//}
//
//// busca un registro de empresa por sus criterios
//func (s *ObtencionCodigoService) buscarRegistroEmpresa(ctx context.Context, request request.SolicitudCuis) (int, error) {
//	query := `
//      SELECT id
//      FROM registroEmpresa
//      WHERE codigo_sistema = $1
//      AND nit = $2
//      AND codigo_ambiente = $3
//      AND codigo_punto_venta = $4
//      AND codigo_sucursal = $5
//      LIMIT 1
//  `
//
//	var id int
//	err := s.DB.QueryRowContext(
//		ctx,
//		query,
//		request.CodigoSistema,
//		request.Nit,
//		request.CodigoAmbiente,
//		request.CodigoPuntoVenta,
//		request.CodigoSucursal,
//	).Scan(&id)
//
//	if err == sql.ErrNoRows {
//		return 0, nil // No existe el registro
//	}
//
//	if err != nil {
//		return 0, err
//	}
//
//	return id, nil
//}
//
//// obtiene la hora actual en la zona horaria de Bolivia
//func (s *ObtencionCodigoService) getCurrentBoliviaTime() (time.Time, error) {
//	loc, err := time.LoadLocation(defaultTimeZone)
//	if err != nil {
//		return time.Time{}, err
//	}
//	return time.Now().In(loc), nil
//}
//
//// parsea la respuesta SOAP para CUIS
//func (s *ObtencionCodigoService) parseSoapCuisResponse(respSoap interface{}) (string, string, bool, error) {
//	resp, ok := respSoap.(response.SoapBodyCuis)
//	if !ok {
//		return "", "", false, fmt.Errorf("%w: %T", ErrUnexpectedRespType, respSoap)
//	}
//
//	return resp.Response.Respuesta.Codigo,
//		resp.Response.Respuesta.FechaVigencia,
//		resp.Response.Respuesta.Transaccion,
//		nil
//}
//
//// crea un nuevo registro de empresa y CUIS
//func (s *ObtencionCodigoService) crearNuevoRegistro(ctx context.Context, request request.SolicitudCuis, respSoap interface{}) error {
//	currentBolivia, err := s.getCurrentBoliviaTime()
//	if err != nil {
//		return err
//	}
//
//	// Parsear respuesta
//	codigoCuis, fechaVigencia, transaccion, err := s.parseSoapCuisResponse(respSoap)
//	if err != nil {
//		return err
//	}
//
//	// Iniciar transacción
//	tx, err := s.DB.BeginTx(ctx, nil)
//	if err != nil {
//		return fmt.Errorf("error al iniciar transacción: %w", err)
//	}
//	defer tx.Rollback()
//
//	// Verificar si ya existe el NIT en la base de datos
//	var existeNIT bool
//	queryVerificacionNIT := `
//      SELECT EXISTS (
//          SELECT 1 FROM registroEmpresa
//          WHERE nit = $1
//      )
//  `
//	err = tx.QueryRowContext(
//		ctx,
//		queryVerificacionNIT,
//		request.Nit,
//	).Scan(&existeNIT)
//
//	if err != nil {
//		return fmt.Errorf("error al verificar existencia del NIT: %w", err)
//	}
//
//	// Si el NIT ya existe, verificar si la combinación de sucursal y punto de venta existe
//	if existeNIT {
//		var existeCombinacion bool
//		queryVerificacionCombinacion := `
//          SELECT EXISTS (
//              SELECT 1 FROM registroEmpresa
//              WHERE nit = $1
//              AND codigo_sucursal = $2
//              AND codigo_punto_venta = $3
//          )
//      `
//		err = tx.QueryRowContext(
//			ctx,
//			queryVerificacionCombinacion,
//			request.Nit,
//			request.CodigoSucursal,
//			request.CodigoPuntoVenta,
//		).Scan(&existeCombinacion)
//
//		if err != nil {
//			return fmt.Errorf("error al verificar combinación de sucursal y punto de venta: %w", err)
//		}
//
//		if existeCombinacion {
//			return fmt.Errorf("ya existe un registro con el mismo NIT, código sucursal y código punto de venta")
//		}
//	}
//
//	// Insertar en registroEmpresa
//	query := `
//      INSERT INTO registroEmpresa (
//          codigo_ambiente,
//          codigo_modalidad,
//          codigo_punto_venta,
//          codigo_sistema,
//          codigo_sucursal,
//          nit
//      ) VALUES ($1, $2, $3, $4, $5, $6)
//      RETURNING id
//  `
//	var registroID int
//	err = tx.QueryRowContext(
//		ctx,
//		query,
//		request.CodigoAmbiente,
//		request.CodigoModalidad,
//		request.CodigoPuntoVenta,
//		request.CodigoSistema,
//		request.CodigoSucursal,
//		request.Nit,
//	).Scan(&registroID)
//	if err != nil {
//		return fmt.Errorf("error al insertar registro: %w", err)
//	}
//
//	// Insertar en cuis
//	queryInsertCuis := `
//      INSERT INTO cuis (cuis, fecha_vigencia, transaccion, fecha_creacion, registro_empresa_id)
//      VALUES ($1, $2, $3, $4, $5)
//  `
//	_, err = tx.ExecContext(ctx, queryInsertCuis, codigoCuis, fechaVigencia, transaccion, currentBolivia, registroID)
//	if err != nil {
//		return fmt.Errorf("error al insertar CUIS: %w", err)
//	}
//
//	if err = tx.Commit(); err != nil {
//		return fmt.Errorf("error al confirmar transacción: %w", err)
//	}
//
//	return nil
//}
//
//// actualiza un registro existente de empresa y CUIS
//func (s *ObtencionCodigoService) actualizarRegistro(ctx context.Context, empresaID int, cuisID int64, req request.SolicitudCuis, respRaw interface{}) error {
//	currentBolivia, err := s.getCurrentBoliviaTime()
//	if err != nil {
//		return err
//	}
//
//	// 1. Iniciar tx
//	tx, err := s.DB.BeginTx(ctx, nil)
//	if err != nil {
//		return fmt.Errorf("iniciar transacción: %w", err)
//	}
//	defer tx.Rollback()
//
//	// 2. Parsear respuesta
//	nuevoCuis, fechaVigencia, _, err := s.parseSoapCuisResponse(respRaw)
//	if err != nil {
//		return err
//	}
//
//	// 3. Actualizar empresa
//	_, err = tx.ExecContext(ctx, `
//      UPDATE registroEmpresa
//      SET codigo_ambiente=$1, codigo_modalidad=$2, codigo_punto_venta=$3,
//          codigo_sistema=$4, codigo_sucursal=$5, nit=$6, fecha_actualizacion=$7
//      WHERE id=$8
//  `,
//		req.CodigoAmbiente, req.CodigoModalidad, req.CodigoPuntoVenta,
//		req.CodigoSistema, req.CodigoSucursal, req.Nit, currentBolivia, empresaID,
//	)
//	if err != nil {
//		return fmt.Errorf("actualizar registroEmpresa: %w", err)
//	}
//
//	// 4. Comprobar si hay un CUIS existente
//	var existingCuis string
//	err = tx.QueryRowContext(ctx, `SELECT cuis FROM cuis WHERE id=$1 AND registro_empresa_id=$2`, cuisID, empresaID).Scan(&existingCuis)
//	if err != nil && err != sql.ErrNoRows {
//		return fmt.Errorf("consultar cuis existente: %w", err)
//	}
//
//	// 5. Insertar o actualizar
//	if err == sql.ErrNoRows {
//		_, err = tx.ExecContext(ctx, `INSERT INTO cuis (registro_empresa_id, cuis) VALUES ($1, $2)`, empresaID, nuevoCuis)
//		if err != nil {
//			return fmt.Errorf("insertar nuevo cuis: %w", err)
//		}
//	} else if existingCuis != nuevoCuis {
//		_, err = tx.ExecContext(ctx, `UPDATE cuis SET cuis=$1, fecha_vigencia=$2, fecha_actualizacion=$3 WHERE id=$4`,
//			nuevoCuis, fechaVigencia, currentBolivia, cuisID)
//		if err != nil {
//			return fmt.Errorf("actualizar cuis existente: %w", err)
//		}
//	}
//
//	// 6. Confirmar tx
//	if err := tx.Commit(); err != nil {
//		return fmt.Errorf("confirmar transacción: %w", err)
//	}
//	return nil
//}
