package handlers

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

	"github.com/labstack/echo/v4"

	"github.com/memohai/memoh/internal/email"
	emailmailgun "github.com/memohai/memoh/internal/email/adapters/mailgun"
)

// EmailWebhookHandler handles inbound email webhooks (Mailgun).
// Modeled after the Feishu WebhookHandler pattern.
type EmailWebhookHandler struct {
	service *email.Service
	manager *email.Manager
	trigger *email.Trigger
	logger  *slog.Logger
}

func NewEmailWebhookHandler(log *slog.Logger, service *email.Service, manager *email.Manager, trigger *email.Trigger) *EmailWebhookHandler {
	return &EmailWebhookHandler{
		service: service,
		manager: manager,
		trigger: trigger,
		logger:  log.With(slog.String("handler", "email_webhook")),
	}
}

func (h *EmailWebhookHandler) Register(e *echo.Echo) {
	e.POST("/email/mailgun/webhook/:config_id", h.HandleMailgun)
}

// HandleMailgun godoc
// @Summary Mailgun inbound email webhook
// @Description Receives inbound emails from Mailgun
// @Tags email-webhook
// @Param config_id path string true "Email provider config ID"
// @Success 200 {object} map[string]string
// @Failure 400 {object} ErrorResponse
// @Failure 403 {object} ErrorResponse
// @Failure 500 {object} ErrorResponse
// @Router /email/mailgun/webhook/{config_id} [post]
func (h *EmailWebhookHandler) HandleMailgun(c echo.Context) error {
	configID := strings.TrimSpace(c.Param("config_id"))
	if configID == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "config_id is required")
	}

	provider, err := h.service.GetProvider(c.Request().Context(), configID)
	if err != nil {
		return echo.NewHTTPError(http.StatusNotFound, "provider not found")
	}

	if provider.Provider != string(emailmailgun.ProviderName) {
		return echo.NewHTTPError(http.StatusBadRequest, "provider is not mailgun")
	}

	mode, _ := provider.Config["inbound_mode"].(string)
	if mode != emailmailgun.InboundModeWebhook {
		return echo.NewHTTPError(http.StatusBadRequest, "provider is not in webhook mode")
	}

	adapter, err := h.service.Registry().Get(emailmailgun.ProviderName)
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "mailgun adapter not available")
	}
	webhookReceiver, ok := adapter.(email.WebhookReceiver)
	if !ok {
		return echo.NewHTTPError(http.StatusInternalServerError, "mailgun adapter does not support webhooks")
	}

	var configMap map[string]any
	configBytes, _ := json.Marshal(provider.Config)
	_ = json.Unmarshal(configBytes, &configMap)

	inbound, err := webhookReceiver.HandleWebhook(c.Request().Context(), configMap, c.Request())
	if err != nil {
		h.logger.Error("webhook handling failed", slog.Any("error", err))
		return echo.NewHTTPError(http.StatusForbidden, err.Error())
	}

	if err := h.trigger.HandleInbound(c.Request().Context(), configID, *inbound); err != nil {
		h.logger.Error("inbound processing failed", slog.Any("error", err))
		return echo.NewHTTPError(http.StatusInternalServerError, "processing failed")
	}

	return c.JSON(http.StatusOK, map[string]string{"status": "ok"})
}
