package app

import (
	"fmt"
	"log"
	"strconv"
	"time"

	"verification-platform-backend/internal/database"
	"verification-platform-backend/internal/model"
	"verification-platform-backend/internal/service"
	"verification-platform-backend/pkg/response"

	"github.com/gin-gonic/gin"
)

func SetupTicketRoutes(r *gin.RouterGroup) {
	r.GET("/tickets", handleAppGetTickets)
	r.GET("/tickets/:id", handleAppGetTicket)
	r.POST("/tickets", handleAppCreateTicket)
	r.POST("/tickets/:id/reply", handleAppReplyTicket)
	r.PUT("/tickets/:id/close", handleAppCloseTicket)
}

func handleAppGetTickets(c *gin.Context) {
	appKey := c.Param("appKey")
	var app model.Application
	if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	if service.GetApplicationDisabledStatus(app.ID) {
		response.Error(c, 403, "该应用已被禁用")
		return
	}

	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "未授权")
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
	statusFilter := c.Query("status")

	query := database.DB.Model(&model.Ticket{}).Where("user_id = ? AND application_id = ?", userID, app.ID)

	if statusFilter != "" {
		query = query.Where("status = ?", statusFilter)
	}

	var total int64
	query.Count(&total)

	offset := (page - 1) * pageSize

	var tickets []model.Ticket
	if err := query.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&tickets).Error; err != nil {
		response.Error(c, 500, "获取工单列表失败")
		return
	}

	response.Success(c, gin.H{
		"tickets":    tickets,
		"total":      total,
		"page":       page,
		"page_size":  pageSize,
		"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
	})
}

func handleAppGetTicket(c *gin.Context) {
	appKey := c.Param("appKey")
	var app model.Application
	if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	if service.GetApplicationDisabledStatus(app.ID) {
		response.Error(c, 403, "该应用已被禁用")
		return
	}

	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "未授权")
		return
	}

	ticketID := c.Param("id")
	var ticket model.Ticket
	if err := database.DB.Where("id = ? AND user_id = ? AND application_id = ?", ticketID, userID, app.ID).
		Preload("Replies").
		First(&ticket).Error; err != nil {
		response.Error(c, 404, "工单不存在")
		return
	}

	response.Success(c, gin.H{
		"ticket": ticket,
	})
}

func handleAppCreateTicket(c *gin.Context) {
	appKey := c.Param("appKey")
	var app model.Application
	if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	if service.GetApplicationDisabledStatus(app.ID) {
		response.Error(c, 403, "该应用已被禁用")
		return
	}

	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "未授权")
		return
	}

	var req struct {
		Title    string `json:"title" binding:"required"`
		Content  string `json:"content" binding:"required"`
		Type     string `json:"type"`
		Priority string `json:"priority"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	if req.Type == "" {
		req.Type = "other"
	}
	if req.Priority == "" {
		req.Priority = "normal"
	}

	ticket := model.Ticket{
		UserID:        userID.(uint),
		ApplicationID: &app.ID,
		Title:         req.Title,
		Content:       req.Content,
		Type:          req.Type,
		Category:      "other",
		Priority:      req.Priority,
		Status:        "open",
		AssignedTo:    &app.UserID,
	}

	if err := database.DB.Create(&ticket).Error; err != nil {
		log.Printf("[ERROR] Failed to create ticket: %v", err)
		response.Error(c, 500, "创建工单失败")
		return
	}

	service.LogOperation(c, "create", "ticket", &ticket.ID, fmt.Sprintf("用户创建工单: %s", ticket.Title), nil)

	response.Success(c, gin.H{
		"id":      ticket.ID,
		"message": "工单创建成功",
	})
}

func handleAppReplyTicket(c *gin.Context) {
	appKey := c.Param("appKey")
	var app model.Application
	if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	if service.GetApplicationDisabledStatus(app.ID) {
		response.Error(c, 403, "该应用已被禁用")
		return
	}

	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "未授权")
		return
	}

	ticketID := c.Param("id")
	var ticket model.Ticket
	if err := database.DB.Where("id = ? AND user_id = ? AND application_id = ?", ticketID, userID, app.ID).First(&ticket).Error; err != nil {
		response.Error(c, 404, "工单不存在")
		return
	}

	if ticket.Status == "closed" {
		response.Error(c, 400, "工单已关闭，无法回复")
		return
	}

	var req struct {
		Content string `json:"content" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, 400, "参数错误")
		return
	}

	reply := model.TicketReply{
		TicketID: parseUint(ticketID),
		UserID:   userID.(uint),
		Content:  req.Content,
	}

	if err := database.DB.Create(&reply).Error; err != nil {
		response.Error(c, 500, "回复失败")
		return
	}

	if ticket.Status == "resolved" || ticket.Status == "processing" {
		ticket.Status = "processing"
		database.DB.Save(&ticket)
	}

	response.Success(c, gin.H{
		"id":      reply.ID,
		"message": "回复成功",
	})
}

func handleAppCloseTicket(c *gin.Context) {
	appKey := c.Param("appKey")
	var app model.Application
	if err := database.DB.Where("app_key = ?", appKey).First(&app).Error; err != nil {
		response.Error(c, 404, "应用不存在")
		return
	}

	if service.GetApplicationDisabledStatus(app.ID) {
		response.Error(c, 403, "该应用已被禁用")
		return
	}

	userID, exists := c.Get("user_id")
	if !exists {
		response.Error(c, 401, "未授权")
		return
	}

	ticketID := c.Param("id")
	var ticket model.Ticket
	if err := database.DB.Where("id = ? AND user_id = ? AND application_id = ?", ticketID, userID, app.ID).First(&ticket).Error; err != nil {
		response.Error(c, 404, "工单不存在")
		return
	}

	if ticket.Status == "closed" {
		response.Error(c, 400, "工单已关闭")
		return
	}

	now := time.Now()
	ticket.Status = "closed"
	ticket.ClosedAt = &now

	if err := database.DB.Save(&ticket).Error; err != nil {
		response.Error(c, 500, "关闭工单失败")
		return
	}

	service.LogOperation(c, "close", "ticket", &ticket.ID, fmt.Sprintf("用户关闭工单: %s", ticket.Title), nil)

	response.Success(c, gin.H{
		"message": "工单已关闭",
	})
}

func parseUint(s string) uint {
	var val uint
	fmt.Sscanf(s, "%d", &val)
	return val
}
