package handler

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

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/warmbly/warmbly/internal/repository"
)

// Internal email-message-map endpoints. Workers call these instead of touching
// Postgres directly (per CLAUDE.md), mirroring the DEK endpoints. Auth via
// middleware.InternalAuthMiddleware (static bearer token in INTERNAL_API_TOKEN).
//
//	PUT    /api/v1/internal/email-message-map  body {user_id,email_id,message_id,id,thread_id} -> 204
//	GET    /api/v1/internal/email-message-map?user_id=&email_id=&message_id=
//	                                            -> 200 {...} | 404 (no mapping)
//	DELETE /api/v1/internal/email-message-map?user_id=&email_id=&message_id=&id= -> 204

type emailMessageMapPayload struct {
	UserID    string `json:"user_id"`
	EmailID   string `json:"email_id"`
	MessageID string `json:"message_id"`
	ID        string `json:"id"`
	ThreadID  string `json:"thread_id"`
}

func (h *Handler) InternalPutEmailMessageMap(c *gin.Context) {
	body, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "read body"})
		return
	}
	var p emailMessageMapPayload
	if err := json.Unmarshal(body, &p); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "decode body"})
		return
	}
	if p.UserID == "" || p.EmailID == "" || p.MessageID == "" || p.ID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "user_id, email_id, message_id, id required"})
		return
	}
	err = h.EmailMessageMap.Add(c.Request.Context(), repository.EmailMessageData{
		UserID:    p.UserID,
		EmailID:   p.EmailID,
		MessageID: p.MessageID,
		ID:        p.ID,
		ThreadID:  p.ThreadID,
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.Status(http.StatusNoContent)
}

func (h *Handler) InternalGetEmailMessageMap(c *gin.Context) {
	userID, emailID, messageID, ok := parseEmailMessageMapKey(c)
	if !ok {
		return
	}
	data, err := h.EmailMessageMap.Get(c.Request.Context(), userID, emailID, messageID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if data == nil {
		c.Status(http.StatusNotFound)
		return
	}
	c.JSON(http.StatusOK, emailMessageMapPayload{
		UserID:    data.UserID,
		EmailID:   data.EmailID,
		MessageID: data.MessageID,
		ID:        data.ID,
		ThreadID:  data.ThreadID,
	})
}

func (h *Handler) InternalDeleteEmailMessageMap(c *gin.Context) {
	userID, emailID, messageID, ok := parseEmailMessageMapKey(c)
	if !ok {
		return
	}
	var id uuid.UUID
	if raw := c.Query("id"); raw != "" {
		parsed, err := uuid.Parse(raw)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"})
			return
		}
		id = parsed
	}
	if err := h.EmailMessageMap.Del(c.Request.Context(), userID, emailID, messageID, id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.Status(http.StatusNoContent)
}

func parseEmailMessageMapKey(c *gin.Context) (userID, emailID uuid.UUID, messageID string, ok bool) {
	var err error
	userID, err = uuid.Parse(c.Query("user_id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid user_id"})
		return uuid.Nil, uuid.Nil, "", false
	}
	emailID, err = uuid.Parse(c.Query("email_id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid email_id"})
		return uuid.Nil, uuid.Nil, "", false
	}
	messageID = c.Query("message_id")
	if messageID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "message_id required"})
		return uuid.Nil, uuid.Nil, "", false
	}
	return userID, emailID, messageID, true
}
