package ai

import (
	"errors"
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"senlinai-agent/backend/internal/httpx"
	"senlinai-agent/backend/internal/logic/auth"
	"senlinai-agent/backend/internal/models"
)

// SessionDTO 是普通项目 AI 会话的公开契约，不携带数据库主键或自动创建对象的 ID。
type SessionDTO struct {
	ID        string    `json:"id"`
	ProjectID string    `json:"projectId"`
	Title     string    `json:"title"`
	Context   string    `json:"context"`
	Status    string    `json:"status"`
	CreatedAt time.Time `json:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt"`
}

type createSessionRequest struct {
	Title   string `json:"title"`
	Context string `json:"context"`
}

// Handler 注册受认证、受项目所有权保护的 AI 会话接口。
type Handler struct {
	service *SessionService
}

func NewHandler(service *SessionService) *Handler {
	return &Handler{service: service}
}

func (h *Handler) Register(router gin.IRouter) {
	router.GET("/projects/:id/ai-sessions", h.list)
	router.POST("/projects/:id/ai-sessions", h.create)
}

func (h *Handler) list(c *gin.Context) {
	userID, projectIdentity, ok := aiRequestContext(c)
	if !ok {
		return
	}
	sessions, err := h.service.List(userID, projectIdentity)
	if err != nil {
		writeAIError(c, err)
		return
	}
	items := make([]SessionDTO, 0, len(sessions))
	for _, session := range sessions {
		items = append(items, sessionDTO(session))
	}
	c.JSON(http.StatusOK, items)
}

func (h *Handler) create(c *gin.Context) {
	userID, projectIdentity, ok := aiRequestContext(c)
	if !ok {
		return
	}
	var input createSessionRequest
	if err := c.ShouldBindJSON(&input); err != nil {
		httpx.Error(c, http.StatusBadRequest, "invalid_request", "请求参数无效")
		return
	}
	session, err := h.service.Create(userID, projectIdentity, input.Title, input.Context)
	if err != nil {
		writeAIError(c, err)
		return
	}
	c.JSON(http.StatusCreated, sessionDTO(*session))
}

func aiRequestContext(c *gin.Context) (uint, string, bool) {
	userID, ok := auth.CurrentUserID(c)
	if !ok {
		httpx.Error(c, http.StatusUnauthorized, "unauthorized", "未登录或登录已失效")
		return 0, "", false
	}
	projectIdentity, ok := httpx.IdentityParam(c, "id")
	if !ok {
		return 0, "", false
	}
	return userID, projectIdentity, true
}

func sessionDTO(session models.SenlinAgentAISession) SessionDTO {
	return SessionDTO{
		ID:        session.Identity,
		ProjectID: session.ProjectIdentity,
		Title:     session.Title,
		Context:   session.Context,
		Status:    aiSessionStatus(session),
		CreatedAt: session.CreatedAt.UTC(),
		UpdatedAt: session.UpdatedAt.UTC(),
	}
}

func writeAIError(c *gin.Context, err error) {
	switch {
	case errors.Is(err, gorm.ErrRecordNotFound):
		httpx.Error(c, http.StatusNotFound, "not_found", "项目不存在或无权访问")
	case errors.Is(err, ErrInvalidSession):
		httpx.Error(c, http.StatusBadRequest, "invalid_request", "请输入 AI 会话标题")
	case errors.Is(err, ErrAIRateLimited):
		httpx.Error(c, http.StatusTooManyRequests, "ai_rate_limited", "AI 请求过于频繁，请稍后重试")
	case errors.Is(err, ErrAIKeyMissing):
		httpx.Error(c, http.StatusServiceUnavailable, "ai_key_missing", "尚未配置可用的 AI 密钥")
	default:
		log.Printf("ai session request failed: %v", err)
		httpx.Error(c, http.StatusInternalServerError, "internal_error", "AI 会话操作失败，请稍后重试")
	}
}
