package api

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

	"github.com/sdp/control-plane/internal/store"
)

type templateReq struct {
	Name          string                 `json:"name"`
	GatewayBranch string                 `json:"gatewayBranch"`
	Services      []store.TemplateService `json:"services"`
}

func (s *Server) handleTemplates(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		ts, err := s.st.ListTemplates()
		if err != nil {
			writeErr(w, http.StatusInternalServerError, err.Error())
			return
		}
		if ts == nil {
			ts = []store.Template{}
		}
		writeJSON(w, http.StatusOK, ts)
	case http.MethodPost:
		var body templateReq
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			http.Error(w, "bad json", http.StatusBadRequest)
			return
		}
		if body.Name == "" {
			writeErr(w, http.StatusBadRequest, "name required")
			return
		}
		t := store.Template{
			ID:            newID(),
			Name:          body.Name,
			GatewayBranch: body.GatewayBranch,
			Services:      body.Services,
		}
		if err := s.st.CreateTemplate(t); err != nil {
			writeErr(w, http.StatusBadRequest, err.Error())
			return
		}
		writeJSON(w, http.StatusOK, t)
	default:
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
	}
}

func (s *Server) handleTemplateByID(w http.ResponseWriter, r *http.Request) {
	id := strings.TrimPrefix(r.URL.Path, "/api/templates/")
	if id == "" || strings.Contains(id, "/") {
		http.Error(w, "not found", http.StatusNotFound)
		return
	}
	switch r.Method {
	case http.MethodGet:
		t, err := s.st.GetTemplate(id)
		if err == store.ErrNotFound {
			http.Error(w, "not found", http.StatusNotFound)
			return
		}
		if err != nil {
			writeErr(w, http.StatusInternalServerError, err.Error())
			return
		}
		writeJSON(w, http.StatusOK, t)
	case http.MethodPut:
		var body templateReq
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			http.Error(w, "bad json", http.StatusBadRequest)
			return
		}
		t := store.Template{
			ID:            id,
			Name:          body.Name,
			GatewayBranch: body.GatewayBranch,
			Services:      body.Services,
		}
		if err := s.st.UpdateTemplate(t); err == store.ErrNotFound {
			http.Error(w, "not found", http.StatusNotFound)
			return
		} else if err != nil {
			writeErr(w, http.StatusInternalServerError, err.Error())
			return
		}
		writeJSON(w, http.StatusOK, t)
	case http.MethodDelete:
		if err := s.st.DeleteTemplate(id); err == store.ErrNotFound {
			http.Error(w, "not found", http.StatusNotFound)
			return
		} else if err != nil {
			writeErr(w, http.StatusInternalServerError, err.Error())
			return
		}
		writeJSON(w, http.StatusOK, map[string]bool{"ok": true})
	default:
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
	}
}
