package api

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

	"github.com/muyue/muyue/internal/memory"
)

func (s *Server) ensureMemoryStore() (*memory.Store, error) {
	if s.memoryStore == nil {
		store, err := memory.NewStore()
		if err != nil {
			return nil, err
		}
		s.memoryStore = store
	}
	return s.memoryStore, nil
}

func (s *Server) handleMemoryList(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		writeError(w, "GET only", http.StatusMethodNotAllowed)
		return
	}

	store, err := s.ensureMemoryStore()
	if err != nil {
		writeError(w, "memory store: "+err.Error(), http.StatusInternalServerError)
		return
	}

	var memType memory.MemoryType
	if t := r.URL.Query().Get("type"); t != "" {
		memType = memory.MemoryType(t)
	}

	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))

	memories, err := store.List(memType, limit, offset)
	if err != nil {
		writeError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	count, _ := store.Count()

	writeJSON(w, map[string]interface{}{
		"memories": memories,
		"count":    len(memories),
		"total":    count,
	})
}

func (s *Server) handleMemoryCreate(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	var body struct {
		Type       string  `json:"type"`
		Key        string  `json:"key"`
		Content    string  `json:"content"`
		Tags       string  `json:"tags,omitempty"`
		Source     string  `json:"source,omitempty"`
		Confidence float64 `json:"confidence,omitempty"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, "invalid request body", http.StatusBadRequest)
		return
	}

	if body.Key == "" || body.Content == "" {
		writeError(w, "key and content are required", http.StatusBadRequest)
		return
	}

	store, err := s.ensureMemoryStore()
	if err != nil {
		writeError(w, "memory store: "+err.Error(), http.StatusInternalServerError)
		return
	}

	memType := memory.MemoryType(body.Type)
	if memType == "" {
		memType = memory.TypeFact
	}

	m := &memory.Memory{
		Type:       memType,
		Key:        body.Key,
		Content:    body.Content,
		Tags:       body.Tags,
		Source:     body.Source,
		Confidence: body.Confidence,
	}
	if m.Confidence == 0 {
		m.Confidence = 0.5
	}

	if err := store.Store(m); err != nil {
		writeError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, map[string]interface{}{
		"created": true,
		"memory":  m,
	})
}

func (s *Server) handleMemoryDelete(w http.ResponseWriter, r *http.Request) {
	if r.Method != "DELETE" {
		writeError(w, "DELETE only", http.StatusMethodNotAllowed)
		return
	}

	id := strings.TrimPrefix(r.URL.Path, "/api/memory/")
	if id == "" {
		writeError(w, "memory id required", http.StatusBadRequest)
		return
	}

	store, err := s.ensureMemoryStore()
	if err != nil {
		writeError(w, "memory store: "+err.Error(), http.StatusInternalServerError)
		return
	}

	if err := store.Delete(id); err != nil {
		writeError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, map[string]interface{}{
		"deleted": true,
		"id":      id,
	})
}

func (s *Server) handleMemoryOperation(w http.ResponseWriter, r *http.Request) {
	path := strings.TrimPrefix(r.URL.Path, "/api/memory/")

	if path == "" {
		s.handleMemoryList(w, r)
		return
	}

	switch r.Method {
	case "DELETE":
		s.handleMemoryDelete(w, r)
	case "GET":
		store, err := s.ensureMemoryStore()
		if err != nil {
			writeError(w, "memory store: "+err.Error(), http.StatusInternalServerError)
			return
		}
		m, err := store.Get(path)
		if err != nil {
			writeError(w, err.Error(), http.StatusNotFound)
			return
		}
		writeJSON(w, m)
	default:
		writeError(w, "method not allowed", http.StatusMethodNotAllowed)
	}
}

func (s *Server) handleMemorySearch(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		writeError(w, "GET only", http.StatusMethodNotAllowed)
		return
	}

	query := r.URL.Query().Get("q")
	if query == "" {
		writeError(w, "query parameter 'q' is required", http.StatusBadRequest)
		return
	}

	store, err := s.ensureMemoryStore()
	if err != nil {
		writeError(w, "memory store: "+err.Error(), http.StatusInternalServerError)
		return
	}

	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	results, err := store.Search(query, limit)
	if err != nil {
		writeError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, map[string]interface{}{
		"results": results,
		"count":   len(results),
		"query":   query,
	})
}

func (s *Server) handleMemoryRecall(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		writeError(w, "GET only", http.StatusMethodNotAllowed)
		return
	}

	query := r.URL.Query().Get("q")

	store, err := s.ensureMemoryStore()
	if err != nil {
		writeError(w, "memory store: "+err.Error(), http.StatusInternalServerError)
		return
	}

	injector := memory.NewInjector(store)
	contextBlock, err := injector.BuildContextBlock(query)
	if err != nil {
		writeError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, map[string]interface{}{
		"context": contextBlock,
		"query":   query,
	})
}

func (s *Server) handleMemoryContext(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		writeError(w, "GET only", http.StatusMethodNotAllowed)
		return
	}

	store, err := s.ensureMemoryStore()
	if err != nil {
		writeError(w, "memory store: "+err.Error(), http.StatusInternalServerError)
		return
	}

	preferences, _ := store.RecallPreferences()
	facts, _ := store.RecallFacts()

	recentCutoff := time.Now().Add(-24 * time.Hour)
	recent, _ := store.RecallRecent(recentCutoff, 10)

	writeJSON(w, map[string]interface{}{
		"preferences": preferences,
		"facts":       facts,
		"recent":      recent,
	})
}
