package controller

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"

	"github.com/AFASystems/presence/internal/pkg/common/appcontext"
	"github.com/AFASystems/presence/internal/pkg/model"
	"github.com/gorilla/mux"
	"github.com/segmentio/kafka-go"
)

func BeaconsListSingleController(appstate *appcontext.AppState) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		id := vars["beacon_id"]
		beacon, ok := appstate.GetBeacon(id)
		if !ok {
			w.Header().Set("Content-Type", "application/json")
			w.WriteHeader(http.StatusNotFound)
			json.NewEncoder(w).Encode(map[string]string{"error": "Beacon not found"})
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(beacon)
	}
}

func BeaconsListController(appstate *appcontext.AppState) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		beacons := appstate.GetAllBeacons()
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(beacons)
	}
}

// Probably define value as interface and then reuse this writer in all of the functions
func sendKafkaMessage(writer *kafka.Writer, value *model.ApiUpdate, ctx context.Context) error {
	valueStr, err := json.Marshal(&value)
	if err != nil {
		fmt.Println("error in encoding: ", err)
		return err
	}
	msg := kafka.Message{
		Value: valueStr,
	}

	if err := writer.WriteMessages(ctx, msg); err != nil {
		fmt.Println("Error in sending kafka message: ", err)
		return err
	}

	return nil
}

func BeaconsDeleteController(writer *kafka.Writer, ctx context.Context, appstate *appcontext.AppState) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		beaconId := vars["beacon_id"]
		apiUpdate := model.ApiUpdate{
			Method: "DELETE",
			ID:     beaconId,
		}

		fmt.Printf("Sending DELETE beacon id: %s message\n", beaconId)

		if err := sendKafkaMessage(writer, &apiUpdate, ctx); err != nil {
			fmt.Println("error in sending Kafka DELETE message")
			http.Error(w, "Error in sending kafka message", 500)
			return
		}

		// If message is succesfully sent delete the beacon from the list
		appstate.RemoveBeacon(beaconId)
		w.Write([]byte("ok"))
	}
}

func BeaconsAddController(writer *kafka.Writer, ctx context.Context) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		decoder := json.NewDecoder(r.Body)
		var inBeacon model.Beacon
		err := decoder.Decode(&inBeacon)
		fmt.Printf("hello world\n")

		if err != nil {
			http.Error(w, err.Error(), 400)
			return
		}
		fmt.Printf("hello world\n")
		fmt.Printf("in beacon: %+v\n", inBeacon)

		if (len(strings.TrimSpace(inBeacon.Name)) == 0) || (len(strings.TrimSpace(inBeacon.ID)) == 0) {
			http.Error(w, "name and beacon_id cannot be blank", 400)
			return
		}

		fmt.Printf("Adding new print here also\n")
		// fmt.Printf("sending POST beacon id: %s message\n", inBeacon.ID)

		apiUpdate := model.ApiUpdate{
			Method: "POST",
			Beacon: inBeacon,
		}

		fmt.Printf("message: %+v\n", apiUpdate)

		if err := sendKafkaMessage(writer, &apiUpdate, ctx); err != nil {
			fmt.Println("error in sending Kafka POST message")
			http.Error(w, "Error in sending kafka message", 500)
			return
		}

		w.Write([]byte("ok"))
	}
}
