package server

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

	"github.com/go-chi/chi/v5"

	"github.com/operator/command-center/internal/simulation"
)

// SimulationDeps wraps the Phase 8 engine.
type SimulationDeps struct {
	Engine *simulation.Engine
}

func (s *Server) handleListSimRuns(w http.ResponseWriter, r *http.Request) {
	if s.simulation == nil {
		http.Error(w, "simulation not configured", http.StatusServiceUnavailable)
		return
	}
	out, err := s.simulation.Engine.List(r.Context(), 100)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"count": len(out), "runs": out})
}

func (s *Server) handleCreateSimRun(w http.ResponseWriter, r *http.Request) {
	if s.simulation == nil {
		http.Error(w, "simulation not configured", http.StatusServiceUnavailable)
		return
	}
	var p simulation.CreateParams
	if err := json.NewDecoder(r.Body).Decode(&p); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	id, err := s.simulation.Engine.Create(r.Context(), p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	// Phase 8 runs inline. Larger replays may move to a background worker.
	if err := s.simulation.Engine.Run(r.Context(), id); err != nil {
		// Don't fail the request — the row exists with status='failed' for inspection.
		s.logger.Warn().Err(err).Int64("run_id", id).Msg("simulation run failed")
	}
	r2, _ := s.simulation.Engine.Get(r.Context(), id)
	writeJSON(w, http.StatusCreated, r2)
}

func (s *Server) handleGetSimRun(w http.ResponseWriter, r *http.Request) {
	if s.simulation == nil {
		http.Error(w, "simulation not configured", http.StatusServiceUnavailable)
		return
	}
	id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
	run, err := s.simulation.Engine.Get(r.Context(), id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}
	writeJSON(w, http.StatusOK, run)
}

func (s *Server) handleDeleteSimRun(w http.ResponseWriter, r *http.Request) {
	if s.simulation == nil {
		http.Error(w, "simulation not configured", http.StatusServiceUnavailable)
		return
	}
	id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
	if err := s.simulation.Engine.Delete(r.Context(), id); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"ok": true})
}

func (s *Server) handlePromoteSimRun(w http.ResponseWriter, r *http.Request) {
	if s.simulation == nil {
		http.Error(w, "simulation not configured", http.StatusServiceUnavailable)
		return
	}
	id, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
	if err := s.simulation.Engine.Promote(r.Context(), id); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"ok": true, "id": id})
}
