package httpservertest_test

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"sync"
	"testing"

	"github.com/AFASystems/presence/internal/pkg/httpserver"
	"github.com/AFASystems/presence/internal/pkg/model"
	"github.com/boltdb/bolt"
	"github.com/gorilla/mux"
)

// Functions beaconsAddHandler, beaconsListHandler, beaconsDeleteHandler
func TestBeaconCRUD(t *testing.T) {
	tmpfile, _ := os.CreateTemp("", "testdb-*.db")
	defer os.Remove(tmpfile.Name())

	db, err := bolt.Open(tmpfile.Name(), 0600, nil)
	if err != nil {
		t.Fatal(err)
	}
	model.Db = db

	ctx := model.AppContext{
		Beacons: model.BeaconsList{
			Beacons: make(map[string]model.Beacon),
			Lock:    sync.RWMutex{},
		},
		ButtonsList: make(map[string]model.Button),
	}

	b := model.Beacon{Name: "B1", Beacon_id: "1"}
	body, err := json.Marshal(b)

	if err != nil {
		t.Fatal(err)
	}

	req := httptest.NewRequest("POST", "/api/beacons", bytes.NewReader(body))
	w := httptest.NewRecorder()

	httpserver.BeaconsAddHandler(&ctx.Beacons)(w, req)

	if w.Code != http.StatusOK {
		t.Fatalf("create failed: %d", w.Code)
	}

	fmt.Println("--------------------------------------------------------------")

	req = httptest.NewRequest("GET", "/api/beacons", nil)
	w = httptest.NewRecorder()

	httpserver.BeaconsListHandler(&ctx.Beacons)(w, req)

	fmt.Println("Status:", w.Code)
	fmt.Println("Body:", w.Body.String())

	fmt.Println("--------------------------------------------------------------")

	newB := model.Beacon{Name: "B2", Beacon_id: "2"}
	newBody, err := json.Marshal(newB)

	if err != nil {
		t.Fatal(err)
	}

	req = httptest.NewRequest("PUT", "/api/beacons", bytes.NewReader(newBody))
	w = httptest.NewRecorder()

	httpserver.BeaconsAddHandler(&ctx.Beacons)(w, req)

	if w.Code != http.StatusOK {
		t.Fatalf("create failed: %d", w.Code)
	}

	req = httptest.NewRequest("GET", "/api/beacons", nil)
	w = httptest.NewRecorder()

	httpserver.BeaconsListHandler(&ctx.Beacons)(w, req)

	fmt.Println("Status:", w.Code)
	fmt.Println("Body:", w.Body.String())

	fmt.Println("--------------------------------------------------------------")

	req = httptest.NewRequest("DELETE", "/api/beacons/1", nil)
	req = mux.SetURLVars(req, map[string]string{"beacon_id": "1"})

	w = httptest.NewRecorder()

	httpserver.BeaconsDeleteHandler(&ctx.Beacons, ctx.ButtonsList)(w, req)

	fmt.Println("Status: ", w.Code)

	fmt.Println("--------------------------------------------------------------")

	req = httptest.NewRequest("GET", "/api/beacons", nil)
	w = httptest.NewRecorder()

	httpserver.BeaconsListHandler(&ctx.Beacons)(w, req)

	fmt.Println("Status:", w.Code)
	fmt.Println("Body:", w.Body.String())

	fmt.Println("--------------------------------------------------------------")
}

func TestSettingsCRUD(t *testing.T) {
	tmpfile, _ := os.CreateTemp("", "testdb-*.db")
	defer os.Remove(tmpfile.Name())

	db, err := bolt.Open(tmpfile.Name(), 0600, nil)
	if err != nil {
		t.Fatal(err)
	}
	model.Db = db

	ctx := model.AppContext{
		Settings: model.Settings{},
	}

	settings := model.Settings{
		Location_confidence:  10,
		Last_seen_threshold:  10,
		Beacon_metrics_size:  10,
		HA_send_interval:     10,
		HA_send_changes_only: true,
	}

	body, err := json.Marshal(settings)
	if err != nil {
		t.Fatal(err)
	}

	req := httptest.NewRequest("POST", "/api/settings", bytes.NewReader(body))
	w := httptest.NewRecorder()

	httpserver.SettingsEditHandler(&ctx.Settings)(w, req)

	fmt.Println("status: ", w.Code)
	if w.Code != http.StatusOK {
		t.Fatalf("create failed: %d", w.Code)
	}

	fmt.Println("--------------------------------------------------------------")

	req = httptest.NewRequest("GET", "/api/settings", nil)
	w = httptest.NewRecorder()

	httpserver.SettingsListHandler(&ctx.Settings)(w, req)

	fmt.Println("Status:", w.Code)
	fmt.Println("Body:", w.Body.String())
}
