package api

import (
	"errors"
	"net/http"
	"strings"

	"github.com/alexei/tinyforge/internal/store"
	"github.com/go-chi/chi/v5"
)

// listApps handles GET /api/apps.
func (s *Server) listApps(w http.ResponseWriter, r *http.Request) {
	out, err := s.store.ListApps()
	if err != nil {
		respondError(w, http.StatusInternalServerError, "list apps")
		return
	}
	respondJSON(w, http.StatusOK, out)
}

// getApp handles GET /api/apps/{id}.
func (s *Server) getApp(w http.ResponseWriter, r *http.Request) {
	id := chi.URLParam(r, "id")
	a, err := s.store.GetAppByID(id)
	if err != nil {
		if errors.Is(err, store.ErrNotFound) {
			respondNotFound(w, "app")
			return
		}
		respondError(w, http.StatusInternalServerError, "get app")
		return
	}
	respondJSON(w, http.StatusOK, a)
}

// createApp handles POST /api/apps. Body: {"name": "...", "description": "..."}.
func (s *Server) createApp(w http.ResponseWriter, r *http.Request) {
	var req struct {
		Name        string `json:"name"`
		Description string `json:"description"`
	}
	if !decodeJSON(w, r, &req) {
		return
	}
	req.Name = strings.TrimSpace(req.Name)
	if req.Name == "" {
		respondError(w, http.StatusBadRequest, "name is required")
		return
	}

	a, err := s.store.CreateApp(store.App{
		Name: req.Name, Description: req.Description,
	})
	if err != nil {
		respondError(w, http.StatusBadRequest, err.Error())
		return
	}
	respondJSON(w, http.StatusCreated, a)
}

// updateApp handles PUT /api/apps/{id}.
func (s *Server) updateApp(w http.ResponseWriter, r *http.Request) {
	id := chi.URLParam(r, "id")
	var req struct {
		Name        string `json:"name"`
		Description string `json:"description"`
	}
	if !decodeJSON(w, r, &req) {
		return
	}
	a, err := s.store.GetAppByID(id)
	if err != nil {
		if errors.Is(err, store.ErrNotFound) {
			respondNotFound(w, "app")
			return
		}
		respondError(w, http.StatusInternalServerError, "get app")
		return
	}
	if name := strings.TrimSpace(req.Name); name != "" {
		a.Name = name
	}
	a.Description = req.Description
	if err := s.store.UpdateApp(a); err != nil {
		respondError(w, http.StatusInternalServerError, "update app")
		return
	}
	respondJSON(w, http.StatusOK, a)
}

// deleteApp handles DELETE /api/apps/{id}. Workloads previously assigned to
// this app become unassigned (app_id cleared), they are NOT deleted.
func (s *Server) deleteApp(w http.ResponseWriter, r *http.Request) {
	id := chi.URLParam(r, "id")
	if err := s.store.DeleteApp(id); err != nil {
		if errors.Is(err, store.ErrNotFound) {
			respondNotFound(w, "app")
			return
		}
		respondError(w, http.StatusInternalServerError, "delete app")
		return
	}
	w.WriteHeader(http.StatusNoContent)
}
