package api

import (
	"errors"
	"net/http"

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

// containerView decorates a stored Container row with the human-readable
// names the global Containers table needs (workload name, app name).
// Decorating server-side avoids N+1 fetches on the frontend.
type containerView struct {
	store.Container
	WorkloadName string `json:"workload_name"`
	AppID        string `json:"app_id,omitempty"`
	AppName      string `json:"app_name,omitempty"`
}

// listAllContainers handles GET /api/containers.
// Query params: workload_id, kind, state, app_id (all optional, AND-combined).
// Returns the global container index, newest first, decorated with workload
// and app names.
func (s *Server) listAllContainers(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	filter := store.ContainerFilter{
		WorkloadID:   q.Get("workload_id"),
		WorkloadKind: q.Get("kind"),
		State:        q.Get("state"),
		AppID:        q.Get("app_id"),
	}

	rows, err := s.store.ListContainers(filter)
	if err != nil {
		respondError(w, http.StatusInternalServerError, "list containers")
		return
	}

	// Pre-load workloads + apps so the join is in-memory rather than per-row.
	workloads, err := s.store.ListWorkloads("")
	if err != nil {
		respondError(w, http.StatusInternalServerError, "list workloads")
		return
	}
	wlByID := make(map[string]store.Workload, len(workloads))
	for _, wl := range workloads {
		wlByID[wl.ID] = wl
	}

	apps, err := s.store.ListApps()
	if err != nil {
		respondError(w, http.StatusInternalServerError, "list apps")
		return
	}
	appByID := make(map[string]store.App, len(apps))
	for _, a := range apps {
		appByID[a.ID] = a
	}

	out := make([]containerView, 0, len(rows))
	for _, c := range rows {
		v := containerView{Container: c}
		if wl, ok := wlByID[c.WorkloadID]; ok {
			v.WorkloadName = wl.Name
			if wl.AppID != "" {
				v.AppID = wl.AppID
				if app, ok := appByID[wl.AppID]; ok {
					v.AppName = app.Name
				}
			}
		}
		out = append(out, v)
	}
	respondJSON(w, http.StatusOK, out)
}

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