//go:build ignore
// NOTE: requires wails dependency in target project — use this file by copying into a Wails project

package infra

import (
	"context"
	"fmt"
	"time"

	"github.com/wailsapp/wails/v2/pkg/runtime"
)

// WailsStreamConfig configura un stream de datos hacia el frontend.
type WailsStreamConfig struct {
	StreamName string        // Nombre del stream (evento base)
	ChunkDelay time.Duration // Delay entre chunks (default 0)
}

// WailsStreamData envía un slice de datos como stream al frontend.
// Emite cada elemento como chunk en {streamName}, y {streamName}:complete al terminar.
func WailsStreamData[T any](ctx context.Context, cfg WailsStreamConfig, data []T) error {
	if cfg.StreamName == "" {
		return fmt.Errorf("stream name is required")
	}

	for _, chunk := range data {
		select {
		case <-ctx.Done():
			runtime.EventsEmit(ctx, cfg.StreamName+":error", map[string]string{
				"message": "stream cancelled",
			})
			return ctx.Err()
		default:
			runtime.EventsEmit(ctx, cfg.StreamName, chunk)
			if cfg.ChunkDelay > 0 {
				time.Sleep(cfg.ChunkDelay)
			}
		}
	}

	runtime.EventsEmit(ctx, cfg.StreamName+":complete", nil)
	return nil
}

// WailsStreamFunc ejecuta una función generadora y envía resultados como stream.
// La función generadora envía datos por el canal, y esta función los retransmite al frontend.
func WailsStreamFunc[T any](ctx context.Context, streamName string, generator func(ctx context.Context, ch chan<- T) error) error {
	ch := make(chan T, 100)
	errCh := make(chan error, 1)

	go func() {
		defer close(ch)
		errCh <- generator(ctx, ch)
	}()

	for chunk := range ch {
		runtime.EventsEmit(ctx, streamName, chunk)
	}

	if err := <-errCh; err != nil {
		runtime.EventsEmit(ctx, streamName+":error", map[string]string{
			"message": err.Error(),
		})
		return err
	}

	runtime.EventsEmit(ctx, streamName+":complete", nil)
	return nil
}
