package app
// Legacy admin handlers retired in favor of ResolveSpec-backed routes.

import (
	"encoding/json"
	"log/slog"
	"net/http"
	"strconv"
	"strings"

	"git.warky.dev/wdevs/amcs/internal/store"
	ext "git.warky.dev/wdevs/amcs/internal/types"

	"github.com/google/uuid"
)

type adminHandlers struct {
	db     *store.DB
	logger *slog.Logger
}

func newAdminHandlers(db *store.DB, logger *slog.Logger) *adminHandlers {
	return &adminHandlers{db: db, logger: logger}
}

func (h *adminHandlers) register(mux *http.ServeMux, middleware func(http.Handler) http.Handler) {
	handle := func(pattern string, fn http.HandlerFunc) {
		mux.Handle(pattern, middleware(fn))
	}

	handle("GET /api/admin/projects", h.listProjects)
	handle("POST /api/admin/projects", h.createProject)
	handle("GET /api/admin/thoughts", h.listThoughts)
	handle("GET /api/admin/thoughts/{id}", h.getThought)
	handle("DELETE /api/admin/thoughts/{id}", h.deleteThought)
	handle("POST /api/admin/thoughts/{id}/archive", h.archiveThought)
	handle("GET /api/admin/skills", h.listSkills)
	handle("DELETE /api/admin/skills/{id}", h.deleteSkill)
	handle("GET /api/admin/guardrails", h.listGuardrails)
	handle("DELETE /api/admin/guardrails/{id}", h.deleteGuardrail)
	handle("GET /api/admin/files", h.listFiles)
	handle("GET /api/admin/stats", h.stats)
}

// --- Projects ---

func (h *adminHandlers) listProjects(w http.ResponseWriter, r *http.Request) {
	projects, err := h.db.ListProjects(r.Context())
	if err != nil {
		h.internalError(w, "list projects", err)
		return
	}
	writeJSON(w, projects)
}

func (h *adminHandlers) createProject(w http.ResponseWriter, r *http.Request) {
	var body struct {
		Name        string `json:"name"`
		Description string `json:"description"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		http.Error(w, "invalid request body", http.StatusBadRequest)
		return
	}
	if strings.TrimSpace(body.Name) == "" {
		http.Error(w, "name is required", http.StatusBadRequest)
		return
	}
	project, err := h.db.CreateProject(r.Context(), body.Name, body.Description)
	if err != nil {
		h.internalError(w, "create project", err)
		return
	}
	w.WriteHeader(http.StatusCreated)
	writeJSON(w, project)
}

// --- Thoughts ---

func (h *adminHandlers) listThoughts(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	limit := 50
	if l := q.Get("limit"); l != "" {
		if n, err := strconv.Atoi(l); err == nil && n > 0 {
			limit = min(n, 200)
		}
	}

	query := strings.TrimSpace(q.Get("q"))
	includeArchived := q.Get("include_archived") == "true"

	var projectID *uuid.UUID
	if pid := q.Get("project_id"); pid != "" {
		if id, err := uuid.Parse(pid); err == nil {
			projectID = &id
		}
	}

	if query != "" {
		results, err := h.db.SearchThoughtsText(r.Context(), query, limit, projectID, nil)
		if err != nil {
			h.internalError(w, "search thoughts", err)
			return
		}
		writeJSON(w, results)
		return
	}

	thoughts, err := h.db.ListThoughts(r.Context(), ext.ListFilter{
		Limit:           limit,
		ProjectID:       projectID,
		IncludeArchived: includeArchived,
	})
	if err != nil {
		h.internalError(w, "list thoughts", err)
		return
	}
	writeJSON(w, thoughts)
}

func (h *adminHandlers) getThought(w http.ResponseWriter, r *http.Request) {
	id, ok := parseUUID(w, r.PathValue("id"))
	if !ok {
		return
	}
	thought, err := h.db.GetThought(r.Context(), id)
	if err != nil {
		h.internalError(w, "get thought", err)
		return
	}
	writeJSON(w, thought)
}

func (h *adminHandlers) deleteThought(w http.ResponseWriter, r *http.Request) {
	id, ok := parseUUID(w, r.PathValue("id"))
	if !ok {
		return
	}
	if err := h.db.DeleteThought(r.Context(), id); err != nil {
		h.internalError(w, "delete thought", err)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

func (h *adminHandlers) archiveThought(w http.ResponseWriter, r *http.Request) {
	id, ok := parseUUID(w, r.PathValue("id"))
	if !ok {
		return
	}
	if err := h.db.ArchiveThought(r.Context(), id); err != nil {
		h.internalError(w, "archive thought", err)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// --- Skills ---

func (h *adminHandlers) listSkills(w http.ResponseWriter, r *http.Request) {
	tag := r.URL.Query().Get("tag")
	skills, err := h.db.ListSkills(r.Context(), tag)
	if err != nil {
		h.internalError(w, "list skills", err)
		return
	}
	writeJSON(w, skills)
}

func (h *adminHandlers) deleteSkill(w http.ResponseWriter, r *http.Request) {
	id, ok := parseUUID(w, r.PathValue("id"))
	if !ok {
		return
	}
	if err := h.db.RemoveSkill(r.Context(), id); err != nil {
		h.internalError(w, "delete skill", err)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// --- Guardrails ---

func (h *adminHandlers) listGuardrails(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	guardrails, err := h.db.ListGuardrails(r.Context(), q.Get("tag"), q.Get("severity"))
	if err != nil {
		h.internalError(w, "list guardrails", err)
		return
	}
	writeJSON(w, guardrails)
}

func (h *adminHandlers) deleteGuardrail(w http.ResponseWriter, r *http.Request) {
	id, ok := parseUUID(w, r.PathValue("id"))
	if !ok {
		return
	}
	if err := h.db.RemoveGuardrail(r.Context(), id); err != nil {
		h.internalError(w, "delete guardrail", err)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// --- Files ---

func (h *adminHandlers) listFiles(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	limit := 100
	if l := q.Get("limit"); l != "" {
		if n, err := strconv.Atoi(l); err == nil && n > 0 {
			limit = min(n, 500)
		}
	}

	filter := ext.StoredFileFilter{Limit: limit}
	if pid := q.Get("project_id"); pid != "" {
		if id, err := uuid.Parse(pid); err == nil {
			filter.ProjectID = &id
		}
	}
	if tid := q.Get("thought_id"); tid != "" {
		if id, err := uuid.Parse(tid); err == nil {
			filter.ThoughtID = &id
		}
	}
	filter.Kind = q.Get("kind")

	files, err := h.db.ListStoredFiles(r.Context(), filter)
	if err != nil {
		h.internalError(w, "list files", err)
		return
	}
	writeJSON(w, files)
}

// --- Stats ---

func (h *adminHandlers) stats(w http.ResponseWriter, r *http.Request) {
	stats, err := h.db.Stats(r.Context())
	if err != nil {
		h.internalError(w, "stats", err)
		return
	}
	writeJSON(w, stats)
}

// --- Helpers ---

func (h *adminHandlers) internalError(w http.ResponseWriter, op string, err error) {
	h.logger.Error("admin handler error", slog.String("op", op), slog.String("error", err.Error()))
	http.Error(w, "internal server error", http.StatusInternalServerError)
}

func writeJSON(w http.ResponseWriter, v any) {
	w.Header().Set("Content-Type", "application/json")
	_ = json.NewEncoder(w).Encode(v)
}

func parseUUID(w http.ResponseWriter, s string) (uuid.UUID, bool) {
	id, err := uuid.Parse(s)
	if err != nil {
		http.Error(w, "invalid id", http.StatusBadRequest)
		return uuid.UUID{}, false
	}
	return id, true
}
