package handlers

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

	"github.com/google/uuid"

	"mgit.msbls.de/m/KanzlAI-mGMT/internal/auth"
	"mgit.msbls.de/m/KanzlAI-mGMT/internal/services"
)

type AIHandler struct {
	ai *services.AIService
}

func NewAIHandler(ai *services.AIService) *AIHandler {
	return &AIHandler{ai: ai}
}

// ExtractDeadlines handles POST /api/ai/extract-deadlines
// Accepts either multipart/form-data with a "file" PDF field, or JSON {"text": "..."}.
func (h *AIHandler) ExtractDeadlines(w http.ResponseWriter, r *http.Request) {
	contentType := r.Header.Get("Content-Type")

	var pdfData []byte
	var text string

	// Check if multipart (PDF upload)
	if len(contentType) >= 9 && contentType[:9] == "multipart" {
		if err := r.ParseMultipartForm(32 << 20); err != nil { // 32MB max
			writeError(w, http.StatusBadRequest, "failed to parse multipart form")
			return
		}
		file, _, err := r.FormFile("file")
		if err != nil {
			writeError(w, http.StatusBadRequest, "missing 'file' field in multipart form")
			return
		}
		defer file.Close()

		pdfData, err = io.ReadAll(file)
		if err != nil {
			writeError(w, http.StatusBadRequest, "failed to read uploaded file")
			return
		}
	} else {
		// Assume JSON body
		var body struct {
			Text string `json:"text"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			writeError(w, http.StatusBadRequest, "invalid request body")
			return
		}
		text = body.Text
	}

	if len(pdfData) == 0 && text == "" {
		writeError(w, http.StatusBadRequest, "provide either a PDF file or text")
		return
	}
	if len(text) > maxDescriptionLen {
		writeError(w, http.StatusBadRequest, "text exceeds maximum length")
		return
	}

	deadlines, err := h.ai.ExtractDeadlines(r.Context(), pdfData, text)
	if err != nil {
		internalError(w, "AI deadline extraction failed", err)
		return
	}

	writeJSON(w, http.StatusOK, map[string]any{
		"deadlines": deadlines,
		"count":     len(deadlines),
	})
}

// SummarizeCase handles POST /api/ai/summarize-case
// Accepts JSON {"case_id": "uuid"}.
func (h *AIHandler) SummarizeCase(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	var body struct {
		CaseID string `json:"case_id"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	if body.CaseID == "" {
		writeError(w, http.StatusBadRequest, "case_id is required")
		return
	}

	caseID, err := parseUUID(body.CaseID)
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid case_id")
		return
	}

	summary, err := h.ai.SummarizeCase(r.Context(), tenantID, caseID)
	if err != nil {
		internalError(w, "AI case summarization failed", err)
		return
	}

	writeJSON(w, http.StatusOK, map[string]string{
		"case_id": caseID.String(),
		"summary": summary,
	})
}

// DraftDocument handles POST /api/ai/draft-document
// Accepts JSON {"case_id": "uuid", "template_type": "string", "instructions": "string", "language": "de|en|fr"}.
func (h *AIHandler) DraftDocument(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	var body struct {
		CaseID       string `json:"case_id"`
		TemplateType string `json:"template_type"`
		Instructions string `json:"instructions"`
		Language     string `json:"language"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	if body.CaseID == "" {
		writeError(w, http.StatusBadRequest, "case_id is required")
		return
	}
	if body.TemplateType == "" {
		writeError(w, http.StatusBadRequest, "template_type is required")
		return
	}

	caseID, err := parseUUID(body.CaseID)
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid case_id")
		return
	}

	if len(body.Instructions) > maxDescriptionLen {
		writeError(w, http.StatusBadRequest, "instructions exceeds maximum length")
		return
	}

	draft, err := h.ai.DraftDocument(r.Context(), tenantID, caseID, body.TemplateType, body.Instructions, body.Language)
	if err != nil {
		internalError(w, "AI document drafting failed", err)
		return
	}

	writeJSON(w, http.StatusOK, draft)
}

// CaseStrategy handles POST /api/ai/case-strategy
// Accepts JSON {"case_id": "uuid"}.
func (h *AIHandler) CaseStrategy(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	var body struct {
		CaseID string `json:"case_id"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	if body.CaseID == "" {
		writeError(w, http.StatusBadRequest, "case_id is required")
		return
	}

	caseID, err := parseUUID(body.CaseID)
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid case_id")
		return
	}

	strategy, err := h.ai.CaseStrategy(r.Context(), tenantID, caseID)
	if err != nil {
		internalError(w, "AI case strategy analysis failed", err)
		return
	}

	writeJSON(w, http.StatusOK, strategy)
}

// SimilarCases handles POST /api/ai/similar-cases
// Accepts JSON {"case_id": "uuid", "description": "string"}.
func (h *AIHandler) SimilarCases(w http.ResponseWriter, r *http.Request) {
	tenantID, ok := auth.TenantFromContext(r.Context())
	if !ok {
		writeError(w, http.StatusForbidden, "missing tenant")
		return
	}

	var body struct {
		CaseID      string `json:"case_id"`
		Description string `json:"description"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	if body.CaseID == "" && body.Description == "" {
		writeError(w, http.StatusBadRequest, "either case_id or description is required")
		return
	}

	if len(body.Description) > maxDescriptionLen {
		writeError(w, http.StatusBadRequest, "description exceeds maximum length")
		return
	}

	var caseID uuid.UUID
	if body.CaseID != "" {
		var err error
		caseID, err = parseUUID(body.CaseID)
		if err != nil {
			writeError(w, http.StatusBadRequest, "invalid case_id")
			return
		}
	}

	cases, err := h.ai.FindSimilarCases(r.Context(), tenantID, caseID, body.Description)
	if err != nil {
		internalError(w, "AI similar case search failed", err)
		return
	}

	writeJSON(w, http.StatusOK, map[string]any{
		"cases": cases,
		"count": len(cases),
	})
}
