package handler

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/warmbly/warmbly/internal/api/middleware"
	"github.com/warmbly/warmbly/internal/errx"
	"github.com/warmbly/warmbly/internal/models"
)

func (h *Handler) EmailsSearch(c *gin.Context) {
	orgID := middleware.GetOrganizationID(c)
	if orgID == nil {
		errx.Handle(c, errx.New(errx.BadRequest, "no organization selected"))
		return
	}

	query := c.Query("q")
	cursor := c.Query("cursor")
	tag := c.Query("tag")
	limit := c.Query("limit")

	resp, err := h.EmailService.Search(c.Request.Context(), orgID.String(), query, cursor, tag, limit, middleware.GetAPIKeyAllowedEmailAccounts(c))
	if err != nil {
		errx.Handle(c, err)
		return
	}

	c.JSON(http.StatusOK, resp)
}

func (h *Handler) GetEmail(c *gin.Context) {
	userID := middleware.GetUserID(c)

	emailAccountID := c.Param("id")

	resp, err := h.EmailService.Get(c.Request.Context(), userID, emailAccountID)
	if err != nil {
		errx.Handle(c, err)
		return
	}

	c.JSON(http.StatusOK, resp)
}

func (h *Handler) UpdateEmail(c *gin.Context) {
	userIDStr := middleware.GetUserID(c)

	emailAccountID := c.Param("id")

	var data models.UpdateEmail

	if err := c.ShouldBindJSON(&data); err != nil {
		errx.Handle(c, errx.ErrInvalid)
		return
	}

	resp, err := h.EmailService.Update(c.Request.Context(), userIDStr, emailAccountID, &data)
	if err != nil {
		errx.Handle(c, err)
		return
	}

	// Audit log
	if accountID, err := uuid.Parse(emailAccountID); err == nil {
		h.auditOrg(c, models.AuditActionUpdate, models.AuditEntityEmailAccount, &accountID, nil, nil)
	}

	c.JSON(http.StatusOK, resp)
}

// StartWarmup enables (or resumes) warmup for a mailbox, preserving ramp
// progress when resuming from a paused state.
func (h *Handler) StartWarmup(c *gin.Context) { h.warmupLifecycle(c, "start") }

// PauseWarmup pauses warmup without losing ramp progress; a later start
// continues from the same daily volume.
func (h *Handler) PauseWarmup(c *gin.Context) { h.warmupLifecycle(c, "pause") }

// ResumeWarmup resumes a paused warmup, shifting the ramp anchor forward so
// progress continues where it left off.
func (h *Handler) ResumeWarmup(c *gin.Context) { h.warmupLifecycle(c, "resume") }

// StopWarmup disables warmup entirely and clears ramp progress — a later
// start begins a fresh ramp. Distinct from PauseWarmup, which preserves
// progress.
func (h *Handler) StopWarmup(c *gin.Context) { h.warmupLifecycle(c, "stop") }

func (h *Handler) warmupLifecycle(c *gin.Context, action string) {
	userIDStr := middleware.GetUserID(c)
	emailAccountID := c.Param("id")

	resp, err := h.EmailService.SetWarmupLifecycle(c.Request.Context(), userIDStr, emailAccountID, action)
	if err != nil {
		errx.Handle(c, err)
		return
	}

	// Seed/repair the warmup chain immediately so warming starts now rather
	// than on the next reconciler pass. Best-effort: the reconciler is the
	// backstop, and pause has nothing to seed.
	if action == "start" || action == "resume" {
		if accountID, perr := uuid.Parse(emailAccountID); perr == nil {
			_ = h.TasksService.EnsureWarmupScheduled(c.Request.Context(), accountID)
		}
	}

	// Audit log
	if accountID, err := uuid.Parse(emailAccountID); err == nil {
		h.auditOrg(c, models.AuditActionUpdate, models.AuditEntityEmailAccount, &accountID, map[string]string{"warmup": action}, nil)
	}

	c.JSON(http.StatusOK, resp)
}

func (h *Handler) UpdateEmailTrackingDomain(c *gin.Context) {
	userIDStr := middleware.GetUserID(c)

	emailAccountID := c.Param("id")
	domain := c.Query("domain")

	status, err := h.EmailService.UpdateTrackingDomain(c.Request.Context(), userIDStr, emailAccountID, domain)
	if err != nil {
		errx.Handle(c, err)
		return
	}

	// Audit log
	if accountID, err := uuid.Parse(emailAccountID); err == nil {
		h.auditOrg(c, models.AuditActionUpdate, models.AuditEntityEmailAccount, &accountID, map[string]string{"tracking_domain": domain}, nil)
	}

	c.JSON(http.StatusOK, status)
}

func (h *Handler) DeleteEmail(c *gin.Context) {
	userIDStr := middleware.GetUserID(c)

	emailAccountID := c.Param("id")

	if err := h.EmailService.Delete(c.Request.Context(), userIDStr, emailAccountID); err != nil {
		errx.Handle(c, err)
		return
	}

	// Audit log
	if accountID, err := uuid.Parse(emailAccountID); err == nil {
		h.auditOrg(c, models.AuditActionDelete, models.AuditEntityEmailAccount, &accountID, nil, nil)
	}

	c.Status(http.StatusNoContent)
}
