package handlers

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"

	"mengpost-backend/models"
	"mengpost-backend/services"
)

func getAccount(c *gin.Context) *models.Account {
	id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
	acc, err := models.GetAccount(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "account not found"})
		return nil
	}
	return acc
}

// GET /api/accounts/:id/mailboxes
func ListMailboxes(c *gin.Context) {
	acc := getAccount(c)
	if acc == nil {
		return
	}
	boxes, err := services.ListMailboxes(acc)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": services.WrapMicrosoftMailErr(acc.Email, err).Error()})
		return
	}
	c.JSON(http.StatusOK, boxes)
}

// GET /api/accounts/:id/messages?mailbox=INBOX&limit=30
func ListMessages(c *gin.Context) {
	acc := getAccount(c)
	if acc == nil {
		return
	}
	mailbox := c.DefaultQuery("mailbox", "INBOX")
	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "30"))
	list, err := services.FetchMessages(acc, mailbox, limit)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": services.WrapMicrosoftMailErr(acc.Email, err).Error()})
		return
	}
	c.JSON(http.StatusOK, list)
}

// GET /api/accounts/:id/messages/:uid?mailbox=INBOX
func GetMessage(c *gin.Context) {
	acc := getAccount(c)
	if acc == nil {
		return
	}
	uid64, _ := strconv.ParseUint(c.Param("uid"), 10, 32)
	mailbox := c.DefaultQuery("mailbox", "INBOX")
	detail, err := services.FetchMessage(acc, mailbox, uint32(uid64))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": services.WrapMicrosoftMailErr(acc.Email, err).Error()})
		return
	}
	c.JSON(http.StatusOK, detail)
}

// POST /api/accounts/:id/send
func SendMessage(c *gin.Context) {
	acc := getAccount(c)
	if acc == nil {
		return
	}
	var body struct {
		To      string `json:"to"`
		Subject string `json:"subject"`
		Body    string `json:"body"`
		HTML    bool   `json:"html"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	log := &models.SentLog{AccountID: acc.ID, To: body.To, Subject: body.Subject, Body: body.Body}
	if err := services.SendMail(acc, body.To, body.Subject, body.Body, body.HTML); err != nil {
		wrapped := services.WrapMicrosoftMailErr(acc.Email, err)
		log.Status = "failed"
		log.Error = wrapped.Error()
		_ = models.AddSentLog(log)
		c.JSON(http.StatusInternalServerError, gin.H{"error": wrapped.Error()})
		return
	}
	log.Status = "ok"
	_ = models.AddSentLog(log)
	c.JSON(http.StatusOK, gin.H{"ok": true})
}

// GET /api/accounts/:id/sent?limit=50
func ListSentLogs(c *gin.Context) {
	acc := getAccount(c)
	if acc == nil {
		return
	}
	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "50"))
	list, err := models.ListSentLogs(acc.ID, limit)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, list)
}
