package api

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

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

type envReq struct {
	Name   string            `json:"name"`
	Values map[string]string `json:"values"`
}

func (s *Server) handleEnvironments(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		envs, err := s.st.ListEnvironments()
		if err != nil {
			writeErr(w, http.StatusInternalServerError, err.Error())
			return
		}
		if envs == nil {
			envs = []store.Environment{}
		}
		writeJSON(w, http.StatusOK, envs)
	case http.MethodPost:
		var body envReq
		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
		}
		if body.Values == nil {
			body.Values = map[string]string{}
		}
		e := store.Environment{ID: newID(), Name: body.Name, Values: body.Values}
		if err := s.st.CreateEnvironment(e); err != nil {
			writeErr(w, http.StatusBadRequest, err.Error())
			return
		}
		writeJSON(w, http.StatusOK, e)
	default:
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
	}
}

func (s *Server) handleEnvironmentByID(w http.ResponseWriter, r *http.Request) {
	id := strings.TrimPrefix(r.URL.Path, "/api/environments/")
	if id == "" || strings.Contains(id, "/") {
		http.Error(w, "not found", http.StatusNotFound)
		return
	}
	switch r.Method {
	case http.MethodGet:
		e, err := s.st.GetEnvironment(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, e)
	case http.MethodPut:
		var body envReq
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			http.Error(w, "bad json", http.StatusBadRequest)
			return
		}
		e, err := s.st.GetEnvironment(id)
		if err == store.ErrNotFound {
			http.Error(w, "not found", http.StatusNotFound)
			return
		}
		if err != nil {
			writeErr(w, http.StatusInternalServerError, err.Error())
			return
		}
		if body.Name != "" {
			e.Name = body.Name
		}
		if body.Values != nil {
			e.Values = body.Values
		}
		if err := s.st.UpdateEnvironment(*e); err != nil {
			writeErr(w, http.StatusInternalServerError, err.Error())
			return
		}
		writeJSON(w, http.StatusOK, e)
	case http.MethodDelete:
		if err := s.st.DeleteEnvironment(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)
	}
}
