// service/cuis_service.go
package services

import (
	"context"
	"daemonService/internal/models/obtencionCodigos"
	"daemonService/internal/models/obtencionCodigos/request"
	"daemonService/internal/utils"
	"database/sql"
	"fmt"
	"log"
	"strconv"
)

type CuisService struct {
	Model  obtencionCodigos.CuisServiceModel
	Logger *log.Logger
}

// En services/cuis_service.go
func NewCuisService(
	model obtencionCodigos.CuisServiceModel, logger *log.Logger,
) *CuisService {
	return &CuisService{Model: model, Logger: logger}
}

// GetName retorna el nombre del servicio
func (s *CuisService) GetName() string {
	return s.Model.Name
}

// logMessage registra un mensaje con el prefijo del servicio
func (s *CuisService) LogMessage(format string, v ...interface{}) {
	if s.Logger != nil {
		s.Logger.Printf(format, v...)
	}
}

// registra un error y devuelve el mismo error
func (s *CuisService) 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...)
}

// crea una solicitud CUIS a partir de datos de empresa
func (s *CuisService) BuildCuisRequestFromEmpresa(ec obtencionCodigos.EmpresaConCuis) request.SolicitudCuisCufd {
	return request.SolicitudCuisCufd{
		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,
		KeyToken:                  ec.TokenKey,
		ValueToken:                ec.TokenValue,
		NombreArchivoClavePrivada: ec.NombreArchivoClavePrivada,
		NombreArchivoCertificado:  ec.NombreArchivoCertificado,
	}
}

// actualiza un registro existente de empresa y CUIS
func (s *CuisService) actualizarRegistro(ctx context.Context, empresaID int, cuisID int64, req request.SolicitudCuisCufd, respRaw interface{}) error {
	currentBolivia, err := utils.GetCurrentBoliviaTime()
	if err != nil {
		return err
	}

	// 1. Iniciar tx
	tx, err := s.Model.DB.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("iniciar transacción: %w", err)
	}
	defer tx.Rollback()

	// 2. Parsear respuesta
	nuevoCuis, fechaVigencia, _, err := utils.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
}
