package handler

import (
    "net/http"
    "strconv"

    "github.com/gin-gonic/gin"
    "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/services"
    "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/models"
)

type SpeakingHandler struct {
	speakingService *services.SpeakingService
}

func NewSpeakingHandler(speakingService *services.SpeakingService) *SpeakingHandler {
	return &SpeakingHandler{speakingService: speakingService}
}

// GetSpeakingScenarios 获取口语场景列表
func (h *SpeakingHandler) GetSpeakingScenarios(c *gin.Context) {
	level := c.Query("level")
	category := c.Query("category")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

    scenarios, total, err := h.speakingService.GetSpeakingScenarios(level, category, page, pageSize)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    c.JSON(http.StatusOK, gin.H{"scenarios": scenarios, "total": total})
}

// GetSpeakingScenario 获取单个口语场景
func (h *SpeakingHandler) GetSpeakingScenario(c *gin.Context) {
	id := c.Param("id")

	scenario, err := h.speakingService.GetSpeakingScenario(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Speaking scenario not found"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"scenario": scenario})
}

// CreateSpeakingScenario 创建口语场景
func (h *SpeakingHandler) CreateSpeakingScenario(c *gin.Context) {
	var scenario models.SpeakingScenario
	if err := c.ShouldBindJSON(&scenario); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

    if err := h.speakingService.CreateSpeakingScenario(&scenario); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    c.JSON(http.StatusCreated, gin.H{"scenario": scenario})
}

// UpdateSpeakingScenario 更新口语场景
func (h *SpeakingHandler) UpdateSpeakingScenario(c *gin.Context) {
	id := c.Param("id")

    var updates models.SpeakingScenario
    if err := c.ShouldBindJSON(&updates); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    if err := h.speakingService.UpdateSpeakingScenario(id, &updates); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    scenario, err := h.speakingService.GetSpeakingScenario(id)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    c.JSON(http.StatusOK, gin.H{"scenario": scenario})
}

// DeleteSpeakingScenario 删除口语场景
func (h *SpeakingHandler) DeleteSpeakingScenario(c *gin.Context) {
	id := c.Param("id")

	if err := h.speakingService.DeleteSpeakingScenario(id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Speaking scenario deleted successfully"})
}

// SearchSpeakingScenarios 搜索口语场景
func (h *SpeakingHandler) SearchSpeakingScenarios(c *gin.Context) {
	keyword := c.Query("keyword")
	level := c.Query("level")
	category := c.Query("category")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

    scenarios, total, err := h.speakingService.SearchSpeakingScenarios(keyword, level, category, page, pageSize)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    c.JSON(http.StatusOK, gin.H{"scenarios": scenarios, "total": total})
}

// GetRecommendedScenarios 获取推荐口语场景
func (h *SpeakingHandler) GetRecommendedScenarios(c *gin.Context) {
	userID := c.GetString("user_id")
	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "5"))

	scenarios, err := h.speakingService.GetRecommendedScenarios(userID, limit)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"scenarios": scenarios})
}

// CreateSpeakingRecord 创建口语记录
func (h *SpeakingHandler) CreateSpeakingRecord(c *gin.Context) {
	var record models.SpeakingRecord
	if err := c.ShouldBindJSON(&record); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	record.UserID = c.GetString("user_id")
	if err := h.speakingService.CreateSpeakingRecord(&record); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"record": record})
}

// UpdateSpeakingRecord 更新口语记录
func (h *SpeakingHandler) UpdateSpeakingRecord(c *gin.Context) {
	id := c.Param("id")

    var updates models.SpeakingRecord
    if err := c.ShouldBindJSON(&updates); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    if err := h.speakingService.UpdateSpeakingRecord(id, &updates); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    record, err := h.speakingService.GetSpeakingRecord(id)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    c.JSON(http.StatusOK, gin.H{"record": record})
}

// GetSpeakingRecord 获取口语记录详情
func (h *SpeakingHandler) GetSpeakingRecord(c *gin.Context) {
	id := c.Param("id")

	record, err := h.speakingService.GetSpeakingRecord(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Speaking record not found"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"record": record})
}

// GetUserSpeakingRecords 获取用户口语记录列表
func (h *SpeakingHandler) GetUserSpeakingRecords(c *gin.Context) {
	userID := c.GetString("user_id")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

	records, total, err := h.speakingService.GetUserSpeakingRecords(userID, page, pageSize)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"records":   records,
		"total":  total,
	})
}

// SubmitSpeaking 提交口语练习
func (h *SpeakingHandler) SubmitSpeaking(c *gin.Context) {
	id := c.Param("id")

	var req struct {
		AudioURL string `json:"audio_url"`
		Transcript string `json:"transcript"`
	}

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

	if err := h.speakingService.SubmitSpeaking(id, req.AudioURL, req.Transcript); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Speaking submitted successfully"})
}

// GradeSpeaking AI评分口语练习
func (h *SpeakingHandler) GradeSpeaking(c *gin.Context) {
	id := c.Param("id")

	var req struct {
		Pronunciation float64 `json:"pronunciation"`
		Fluency      float64 `json:"fluency"`
		Accuracy     float64 `json:"accuracy"`
		Score        float64 `json:"score"`
		Feedback     string  `json:"feedback"`
		Suggestions  string  `json:"suggestions"`
	}

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

	if err := h.speakingService.GradeSpeaking(id, req.Pronunciation, req.Fluency, req.Accuracy, req.Score, req.Feedback, req.Suggestions); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Speaking graded successfully"})
}

// GetUserSpeakingStats 获取用户口语统计
func (h *SpeakingHandler) GetUserSpeakingStats(c *gin.Context) {
	userID := c.GetString("user_id")

	stats, err := h.speakingService.GetUserSpeakingStats(userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"stats": stats})
}

// GetSpeakingProgress 获取口语进度
func (h *SpeakingHandler) GetSpeakingProgress(c *gin.Context) {
	userID := c.GetString("user_id")
	scenarioID := c.Param("scenario_id")

	progress, err := h.speakingService.GetSpeakingProgress(userID, scenarioID)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Speaking progress not found"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"progress": progress})
}