package controller

import (
	"log"
	"net/http"
	"strconv"

	"github.com/2930134478/AI-CS/backend/service"
	"github.com/gin-gonic/gin"
)

// DocumentController 文档控制器
type DocumentController struct {
	documentService       *service.DocumentService
	embeddingConfigService *service.EmbeddingConfigService
	users                 *service.UserService
}

// NewDocumentController 创建文档控制器实例
func NewDocumentController(documentService *service.DocumentService, embeddingConfigService *service.EmbeddingConfigService, users *service.UserService) *DocumentController {
	return &DocumentController{
		documentService:       documentService,
		embeddingConfigService: embeddingConfigService,
		users:                 users,
	}
}

func (c *DocumentController) checkKBAccess(ctx *gin.Context) bool {
	userID := getUserIDFromHeader(ctx)
	if userID == 0 {
		return true
	}
	if err := c.embeddingConfigService.CheckKnowledgeBaseAccess(userID); err != nil {
		ctx.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
		return false
	}
	return true
}

// ListDocuments 获取文档列表
func (c *DocumentController) ListDocuments(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	// 获取查询参数
	kbIDStr := ctx.Query("knowledge_base_id")
	pageStr := ctx.DefaultQuery("page", "1")
	pageSizeStr := ctx.DefaultQuery("page_size", "20")
	keyword := ctx.Query("keyword")
	status := ctx.Query("status")

	var knowledgeBaseID uint
	if kbIDStr != "" {
		id, err := strconv.ParseUint(kbIDStr, 10, 64)
		if err == nil {
			knowledgeBaseID = uint(id)
		}
	}

	page, _ := strconv.Atoi(pageStr)
	pageSize, _ := strconv.Atoi(pageSizeStr)

	result, err := c.documentService.ListDocuments(knowledgeBaseID, page, pageSize, keyword, status)
	if err != nil {
		log.Printf("获取文档列表失败: %v", err)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "获取文档列表失败"})
		return
	}

	ctx.JSON(http.StatusOK, result)
}

// GetDocument 获取文档详情
func (c *DocumentController) GetDocument(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil || id == 0 {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
		return
	}

	doc, err := c.documentService.GetDocument(uint(id))
	if err != nil {
		log.Printf("获取文档详情失败: %v", err)
		ctx.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}

	ctx.JSON(http.StatusOK, doc)
}

// CreateDocument 创建文档
func (c *DocumentController) CreateDocument(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	var req struct {
		KnowledgeBaseID uint   `json:"knowledge_base_id" binding:"required"`
		Title           string `json:"title" binding:"required"`
		Content         string `json:"content" binding:"required"`
		Summary         string `json:"summary"`
		Type            string `json:"type"`
		Status          string `json:"status"`
	}

	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	doc, err := c.documentService.CreateDocument(service.CreateDocumentInput{
		KnowledgeBaseID: req.KnowledgeBaseID,
		Title:           req.Title,
		Content:         req.Content,
		Summary:         req.Summary,
		Type:            req.Type,
		Status:          req.Status,
	})
	if err != nil {
		log.Printf("创建文档失败: %v", err)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	ctx.JSON(http.StatusOK, doc)
}

// UpdateDocument 更新文档
func (c *DocumentController) UpdateDocument(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil || id == 0 {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
		return
	}

	var req struct {
		Title   *string `json:"title"`
		Content *string `json:"content"`
		Summary *string `json:"summary"`
		Type    *string `json:"type"`
		Status  *string `json:"status"`
	}

	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	doc, err := c.documentService.UpdateDocument(uint(id), service.UpdateDocumentInput{
		Title:   req.Title,
		Content: req.Content,
		Summary: req.Summary,
		Type:    req.Type,
		Status:  req.Status,
	})
	if err != nil {
		log.Printf("更新文档失败: %v", err)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	ctx.JSON(http.StatusOK, doc)
}

// DeleteDocument 删除文档
func (c *DocumentController) DeleteDocument(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil || id == 0 {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
		return
	}

	if err := c.documentService.DeleteDocument(uint(id)); err != nil {
		log.Printf("删除文档失败: %v", err)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}

// SearchDocuments 向量检索搜索文档
func (c *DocumentController) SearchDocuments(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	query := ctx.Query("query")
	topKStr := ctx.DefaultQuery("top_k", "5")
	kbIDStr := ctx.Query("knowledge_base_id")

	if query == "" {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "查询内容不能为空"})
		return
	}

	topK, _ := strconv.Atoi(topKStr)
	if topK <= 0 {
		topK = 5
	}

	var knowledgeBaseID *uint
	if kbIDStr != "" {
		id, err := strconv.ParseUint(kbIDStr, 10, 64)
		if err == nil {
			kbID := uint(id)
			knowledgeBaseID = &kbID
		}
	}

	docs, err := c.documentService.SearchDocuments(query, topK, knowledgeBaseID)
	if err != nil {
		log.Printf("搜索文档失败: %v", err)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "向量检索失败: " + err.Error()})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"count":     len(docs),
		"documents": docs,
	})
}

// HybridSearchDocuments 混合检索搜索文档（当前实现与向量检索相同）
func (c *DocumentController) HybridSearchDocuments(ctx *gin.Context) {
	c.SearchDocuments(ctx)
}

// UpdateDocumentStatus 更新文档状态
func (c *DocumentController) UpdateDocumentStatus(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil || id == 0 {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
		return
	}

	var req struct {
		Status string `json:"status" binding:"required"`
	}

	if err := ctx.ShouldBindJSON(&req); err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if err := c.documentService.UpdateDocumentStatus(uint(id), req.Status); err != nil {
		log.Printf("更新文档状态失败: %v", err)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{"message": "更新成功"})
}

// PublishDocument 发布文档
func (c *DocumentController) PublishDocument(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil || id == 0 {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
		return
	}

	if err := c.documentService.PublishDocument(uint(id)); err != nil {
		log.Printf("发布文档失败: %v", err)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{"message": "发布成功"})
}

// UnpublishDocument 取消发布文档
func (c *DocumentController) UnpublishDocument(ctx *gin.Context) {
	if !requirePermission(ctx, c.users, string(service.PermKnowledge)) {
		return
	}
	if !c.checkKBAccess(ctx) {
		return
	}
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil || id == 0 {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "文档 ID 不合法"})
		return
	}

	if err := c.documentService.UnpublishDocument(uint(id)); err != nil {
		log.Printf("取消发布文档失败: %v", err)
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{"message": "取消发布成功"})
}
