package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/nats-io/nats.go/jetstream"
	"golang.source-fellows.com/seminar/event-sourcing/pkg/model"
	"log"
	"time"
)
import cloudevents "github.com/cloudevents/sdk-go/v2"
import "github.com/nats-io/nats.go"

var positionStreamName = "positionStream"
var newPositionSubjectName = "position.new"

func main() {

	configureNats()

	ctx := context.Background()
	startTime := time.Date(2024, 8, 1, 11, 15, 0, 0, time.UTC)
	sendPosition(ctx, "Bergen Fjord", model.Position{Lat: 57.593281, Lon: 9.971568}, startTime)
	sendPosition(ctx, "Bergen Fjord", model.Position{Lat: 58.973145, Lon: 5.728900}, startTime.Add(10*time.Hour))
	sendPosition(ctx, "Bergen Fjord", model.Position{Lat: 60.387940, Lon: 5.331789}, startTime.Add(4*time.Hour))

}

func sendPosition(ctx context.Context, name string, pos model.Position, timestamp time.Time) {
	nc, err := nats.Connect(nats.DefaultURL)
	if err != nil {
		log.Fatalf("failed to create connection, %v", err)
	}
	js, err := jetstream.New(nc)
	if err != nil {
		log.Fatalf("failed to create jetstream, %v", err)
	}

	event, err := eventForMovement(name, pos, timestamp)
	if err != nil {
		log.Fatalf("could not build event %v", err)
	}

	jsonBytes, err := event.MarshalJSON()
	if err != nil {
		log.Fatalf("could not build event %v", err)
	}

	ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()
	pubAck, err := js.Publish(ctx, newPositionSubjectName, jsonBytes)
	if err != nil {
		log.Fatalf("could not sent event %v", err)
	}

	log.Println(pubAck)

}

func eventForMovement(name string, pos model.Position, timestamp time.Time) (cloudevents.Event, error) {

	movement := model.Movement{ShipName: name, ToPosition: pos, TimeStamp: timestamp}

	movementJson, err := json.Marshal(movement)
	if err != nil {
		return cloudevents.Event{}, err
	}

	// Create an Event.
	event := cloudevents.NewEvent()
	event.SetSource("source-fellows.com/ship-movement")
	event.SetType("source-fellows.com/ship-movement/position")
	err = event.SetData(cloudevents.ApplicationJSON, movementJson)
	if err != nil {
		return cloudevents.Event{}, err
	}

	return event, nil
}

func configureNats() error {

	nc, err := nats.Connect(nats.DefaultURL)
	if err != nil {
		return fmt.Errorf("failed to create connection, %w", err)
	}
	js, err := nc.JetStream()
	if err != nil {
		return fmt.Errorf("failed to create jetstream connection, %w", err)
	}
	_, err = js.AddStream(&nats.StreamConfig{
		Name:     positionStreamName,
		Subjects: []string{newPositionSubjectName},
		MaxMsgs:  10000,
	})
	fmt.Println(err)

	return nil
}
