package api2

import (
	"context"
	"time"

	"api-soap-facturacion/internal/config"
	"api-soap-facturacion/internal/logger"
	"api-soap-facturacion/pkg/errors"
	"api-soap-facturacion/pkg/soap"
	"github.com/google/uuid"
)

// Client es la interfaz para el cliente de API2
type Client interface {
	ProcessTransaction(ctx context.Context, request TransactionRequest) (*TransactionResponse, error)
	// Agregar más métodos según sea necesario
}

// client implementa la interfaz Client
type client struct {
	soapClient soap.Client
	logger     logger.Logger
}

// crea un nuevo cliente para API2
func NewClient(config config.APIConfig, log logger.Logger) Client {
	// Configurar cliente SOAP
	options := soap.ClientOptions{
		Endpoint: config.Endpoint,
		Username: config.Username,
		Password: config.Password,
		Timeout:  config.Timeout * time.Second,
		Headers: map[string]string{
			"User-Agent": "soap-api-client/1.0",
		},
	}

	return &client{
		soapClient: soap.NewClient(options),
		logger:     log,
	}
}

// ProcessTransaction realiza una solicitud de procesamiento de transacción a API2
func (c *client) ProcessTransaction(ctx context.Context, request TransactionRequest) (*TransactionResponse, error) {
	// Generar ID de solicitud si no existe
	var requestID string
	if id, ok := ctx.Value(soap.RequestIDKey{}).(string); ok {
		requestID = id
	} else {
		requestID = uuid.New().String()
		ctx = context.WithValue(ctx, soap.RequestIDKey{}, requestID)
	}

	// Crear request
	soapRequest := TransactionSoapRequest{
		Request: request,
	}

	// Registrar solicitud
	c.logger.Debug("Enviando solicitud de transacción a API2",
		logger.NewField("request_id", requestID),
		logger.NewField("transaction_id", request.TransactionID),
		logger.NewField("amount", request.Amount),
	)

	// Respuesta
	response := &TransactionSoapResponse{}

	// Realizar llamada SOAP
	startTime := time.Now()
	err := c.soapClient.Call(ctx, "ProcessTransaction", soapRequest, response)
	duration := time.Since(startTime)

	// Manejar error
	if err != nil {
		c.logger.Error("Error al realizar solicitud de transacción a API2",
			logger.NewField("request_id", requestID),
			logger.NewField("transaction_id", request.TransactionID),
			logger.NewField("error", err),
			logger.NewField("duration_ms", duration.Milliseconds()),
		)
		return nil, errors.Wrap(err, "error en solicitud de transacción a API2")
	}

	// Registrar respuesta exitosa
	c.logger.Debug("Respuesta recibida de API2 para transacción",
		logger.NewField("request_id", requestID),
		logger.NewField("transaction_id", request.TransactionID),
		logger.NewField("duration_ms", duration.Milliseconds()),
		logger.NewField("result_code", response.Response.ResultCode),
	)

	return &response.Response, nil
}
