// Package api 提供 REST API 处理函数。
package api

import (
	"net/http"

	"github.com/gin-gonic/gin"

	"github.com/hhs/camtalk/internal/models"
	"github.com/hhs/camtalk/internal/session"
	"github.com/hhs/camtalk/internal/trace"
)

// SessionHandler 提供会话相关的 REST 端点。
type SessionHandler struct {
	sessionMgr session.Manager
}

// NewSessionHandler 创建 SessionHandler。
func NewSessionHandler(sessionMgr session.Manager) *SessionHandler {
	return &SessionHandler{sessionMgr: sessionMgr}
}

// CreateSessionRequest POST /api/sessions 请求体（所有字段可选）。
type CreateSessionRequest struct {
	Config *models.SessionConfig `json:"config,omitempty"`
}

// CreateSession POST /api/sessions — 创建新会话。
func (h *SessionHandler) CreateSession(c *gin.Context) {
	log := trace.FromContext(c.Request.Context())

	var req CreateSessionRequest
	// 请求体可选，解析失败不报错（使用默认配置）
	_ = c.ShouldBindJSON(&req)

	cfg := models.DefaultConfig()
	if req.Config != nil {
		cfg = *req.Config
	}

	sessionID, err := h.sessionMgr.Create(c.Request.Context(), "", cfg)
	if err != nil {
		log.Errorw("create session failed",
			"error", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    "INTERNAL_ERROR",
			"message": "failed to create session",
		})
		return
	}

	// 获取创建后的会话以返回 created_at
	sess, err := h.sessionMgr.Get(c.Request.Context(), sessionID)
	if err != nil {
		log.Errorw("retrieve created session failed",
			"session_id", sessionID,
			"error", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    "INTERNAL_ERROR",
			"message": "failed to retrieve created session",
		})
		return
	}

	log.Infow("session created",
		"session_id", sess.ID)
	c.JSON(http.StatusCreated, gin.H{
		"session_id": sess.ID,
		"created_at": sess.CreatedAt,
	})
}

// DestroySession DELETE /api/sessions/:id — 销毁会话。
func (h *SessionHandler) DestroySession(c *gin.Context) {
	log := trace.FromContext(c.Request.Context())
	sessionID := c.Param("id")

	err := h.sessionMgr.Destroy(c.Request.Context(), sessionID)
	if err != nil {
		if err == session.ErrSessionNotFound {
			c.JSON(http.StatusNotFound, gin.H{
				"code":    "SESSION_NOT_FOUND",
				"message": "session not found or already expired",
			})
			return
		}
		log.Errorw("destroy session failed",
			"session_id", sessionID,
			"error", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    "INTERNAL_ERROR",
			"message": "failed to destroy session",
		})
		return
	}

	log.Infow("session destroyed",
		"session_id", sessionID)
	c.Status(http.StatusNoContent)
}

// RegisterRoutes 注册会话相关路由到给定的路由组。
func (h *SessionHandler) RegisterRoutes(rg *gin.RouterGroup) {
	rg.POST("/sessions", h.CreateSession)
	rg.DELETE("/sessions/:id", h.DestroySession)
}
