package httpserver

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

	"github.com/tim/cairnquire/apps/server/internal/docs"
)

type adminUserInput struct {
	Email       string `json:"email"`
	DisplayName string `json:"displayName"`
	Role        string `json:"role"`
}

type adminSettingsInput struct {
	SignupsEnabled bool `json:"signupsEnabled"`
}

func (s *Server) handleAdminLogin(w http.ResponseWriter, r *http.Request) {
	var input adminUserInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeJSONWithStatus(w, http.StatusBadRequest, map[string]string{"error": "invalid json"})
		return
	}

	user, ok := s.normalizeAdminUserInput(input)
	if !ok {
		writeJSONWithStatus(w, http.StatusBadRequest, map[string]string{"error": "email is required"})
		return
	}
	if user.Role == "viewer" {
		user.Role = "admin"
	}

	created, err := s.repository.UpsertUser(r.Context(), user)
	if err != nil {
		writeJSONWithStatus(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
		return
	}

	writeJSON(w, http.StatusOK, map[string]any{
		"user": created,
		"session": map[string]any{
			"mode":      "foundation",
			"createdAt": time.Now().UTC(),
		},
	})
}

func (s *Server) handleAdminUsers(w http.ResponseWriter, r *http.Request) {
	users, err := s.repository.ListUsers(r.Context())
	if err != nil {
		writeJSONWithStatus(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"users": users})
}

func (s *Server) handleAdminCreateUser(w http.ResponseWriter, r *http.Request) {
	var input adminUserInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeJSONWithStatus(w, http.StatusBadRequest, map[string]string{"error": "invalid json"})
		return
	}

	user, ok := s.normalizeAdminUserInput(input)
	if !ok {
		writeJSONWithStatus(w, http.StatusBadRequest, map[string]string{"error": "email is required"})
		return
	}

	created, err := s.repository.UpsertUser(r.Context(), user)
	if err != nil {
		writeJSONWithStatus(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
		return
	}
	writeJSONWithStatus(w, http.StatusCreated, map[string]any{"user": created})
}

func (s *Server) handleAdminWorkspace(w http.ResponseWriter, r *http.Request) {
	documents, err := s.documents.ListDocuments(r.Context())
	if err != nil {
		writeJSONWithStatus(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
		return
	}
	users, err := s.repository.ListUsers(r.Context())
	if err != nil {
		writeJSONWithStatus(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
		return
	}

	writeJSON(w, http.StatusOK, map[string]any{
		"workspace": map[string]any{
			"sourceDir":     s.config.Content.SourceDir,
			"storeDir":      s.config.Content.StoreDir,
			"databasePath":  s.config.Database.Path,
			"documentCount": len(documents),
			"userCount":     len(users),
		},
		"documents": documents,
	})
}

func (s *Server) handleAdminWorkspaceSync(w http.ResponseWriter, r *http.Request) {
	changes, err := s.documents.SyncSourceDir(r.Context())
	if err != nil {
		writeJSONWithStatus(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{
		"changes":  changes,
		"syncedAt": time.Now().UTC(),
	})
}

func (s *Server) handleAdminSettings(w http.ResponseWriter, r *http.Request) {
	settings, err := s.auth.GetInstanceSettings(r.Context())
	if err != nil {
		writeJSONWithStatus(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"settings": settings})
}

func (s *Server) handleAdminSettingsUpdate(w http.ResponseWriter, r *http.Request) {
	principal, _ := requirePrincipal(r)
	var input adminSettingsInput
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeJSONWithStatus(w, http.StatusBadRequest, map[string]string{"error": "invalid json"})
		return
	}
	settings, err := s.auth.UpdateSignupsEnabled(r.Context(), principal, input.SignupsEnabled)
	if err != nil {
		writeJSONWithStatus(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
		return
	}
	writeJSON(w, http.StatusOK, map[string]any{"settings": settings})
}

func (s *Server) normalizeAdminUserInput(input adminUserInput) (docs.UserRecord, bool) {
	email := strings.TrimSpace(strings.ToLower(input.Email))
	if email == "" {
		return docs.UserRecord{}, false
	}

	role := strings.TrimSpace(strings.ToLower(input.Role))
	switch role {
	case "admin", "editor", "viewer":
	default:
		role = "viewer"
	}

	displayName := strings.TrimSpace(input.DisplayName)
	if displayName == "" {
		displayName = email
	}

	return docs.UserRecord{
		Email:       email,
		DisplayName: displayName,
		Role:        role,
	}, true
}
