package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"github.com/tidbcloud/account/pkg/docker_db/db"
	"github.com/tidbcloud/account/pkg/docker_db/db/impl"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

var (
	model string
	stop  = make(chan bool, 1)
)

func init() {
	flag.StringVar(&model, "model", "start", "server command mode")
	flag.Parse()
}

func main() {
	if model == "start" {
		impl.ReleaseAll()
		http.HandleFunc("/info", info)
		http.HandleFunc("/borrow", borrow)
		http.HandleFunc("/release", release)
		http.HandleFunc("/releaseAll", releaseAll)
		http.HandleFunc("/shutdown", shutdown)
		db.Manager = &db.ExternalProcessManager{}
		go func() {
			_ = http.ListenAndServe(fmt.Sprintf(":%d", db.ServerPort), nil)
		}()
		go shutdownHook()
		<-stop
		fmt.Println("shutdown")
		os.Exit(0)
	}
	shutdownServer()
}

func shutdownHook() {
	fmt.Println("Listening signals...")
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	<-c
	fmt.Println("shutdown....")
	impl.ReleaseAll()
	close(stop)
}

func info(w http.ResponseWriter, r *http.Request) {
	dbs := impl.GetDBs()
	data, err := json.Marshal(dbs)
	if err != nil {
		tilog.Error(r.Context(), "failed to marshal data", zap.Error(err))
		w.WriteHeader(503)
	} else {
		_, _ = w.Write(data)
	}
}

func borrow(w http.ResponseWriter, r *http.Request) {
	d, err := impl.BorrowDB()
	if err != nil {
		tilog.Error(r.Context(), "failed to created db", zap.Error(err))
		w.WriteHeader(503)
	} else {
		data, err := json.Marshal(d)
		if err != nil {
			tilog.Error(r.Context(), "failed to marshal data", zap.Error(err))
			w.WriteHeader(503)
		} else {
			_, _ = w.Write(data)
		}
	}
}

func release(w http.ResponseWriter, r *http.Request) {
	id := r.URL.Query().Get("id")
	impl.ReleaseDB(id)
	w.WriteHeader(200)
}

func releaseAll(w http.ResponseWriter, _ *http.Request) {
	impl.ReleaseAll()
	w.WriteHeader(200)
}

func shutdown(w http.ResponseWriter, _ *http.Request) {
	impl.ReleaseAll()
	w.WriteHeader(200)
	stop <- true
}

func shutdownServer() {
	resp, _ := http.Get(fmt.Sprintf("http://127.0.0.1:%d/shutdown", db.ServerPort))
	if resp != nil {
		_ = resp.Body.Close()
	}
}
