package service

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/model"
)

// AIService AI服务接口
type AIService interface {
	// 写作批改
	CorrectWriting(ctx context.Context, content string, taskType string) (*model.WritingCorrection, error)
	// 口语评估
	EvaluateSpeaking(ctx context.Context, audioText string, prompt string) (*model.SpeakingEvaluation, error)
	// 智能推荐
	GetRecommendations(ctx context.Context, userLevel string, learningHistory []string) (*model.AIRecommendation, error)
	// 生成练习题
	GenerateExercise(ctx context.Context, content string, exerciseType string) (*model.Exercise, error)
}

type aiService struct {
	apiKey  string
	baseURL string
	client  *http.Client
}

// NewAIService 创建AI服务实例
func NewAIService() AIService {
	apiKey := os.Getenv("OPENAI_API_KEY")
	baseURL := os.Getenv("OPENAI_BASE_URL")
	if baseURL == "" {
		baseURL = "https://api.openai.com/v1"
	}

	return &aiService{
		apiKey:  apiKey,
		baseURL: baseURL,
		client: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

// OpenAI API请求结构
type openAIRequest struct {
	Model       string    `json:"model"`
	Messages    []message `json:"messages"`
	MaxTokens   int       `json:"max_tokens"`
	Temperature float64   `json:"temperature"`
}

type message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type openAIResponse struct {
	Choices []struct {
		Message message `json:"message"`
	} `json:"choices"`
	Error *struct {
		Message string `json:"message"`
		Type    string `json:"type"`
	} `json:"error,omitempty"`
}

// callOpenAI 调用OpenAI API
func (s *aiService) callOpenAI(ctx context.Context, prompt string) (string, error) {
	if s.apiKey == "" {
		return "", fmt.Errorf("OpenAI API key not configured")
	}

	reqBody := openAIRequest{
		Model: "gpt-3.5-turbo",
		Messages: []message{
			{
				Role:    "user",
				Content: prompt,
			},
		},
		MaxTokens:   1000,
		Temperature: 0.7,
	}

	jsonData, err := json.Marshal(reqBody)
	if err != nil {
		return "", fmt.Errorf("failed to marshal request: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, "POST", s.baseURL+"/chat/completions", bytes.NewBuffer(jsonData))
	if err != nil {
		return "", fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+s.apiKey)

	resp, err := s.client.Do(req)
	if err != nil {
		return "", fmt.Errorf("failed to send request: %w", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("failed to read response: %w", err)
	}

	var openAIResp openAIResponse
	if err := json.Unmarshal(body, &openAIResp); err != nil {
		return "", fmt.Errorf("failed to unmarshal response: %w", err)
	}

	if openAIResp.Error != nil {
		return "", fmt.Errorf("OpenAI API error: %s", openAIResp.Error.Message)
	}

	if len(openAIResp.Choices) == 0 {
		return "", fmt.Errorf("no response from OpenAI")
	}

	return openAIResp.Choices[0].Message.Content, nil
}

// CorrectWriting 写作批改
func (s *aiService) CorrectWriting(ctx context.Context, content string, taskType string) (*model.WritingCorrection, error) {
	prompt := fmt.Sprintf(`请对以下英语写作进行批改，任务类型：%s

写作内容：
%s

请按照以下JSON格式返回批改结果：
{
  "overall_score": 85,
  "grammar_score": 80,
  "vocabulary_score": 90,
  "structure_score": 85,
  "content_score": 88,
  "corrections": [
    {
      "original": "错误的句子",
      "corrected": "修正后的句子",
      "explanation": "修改说明",
      "error_type": "grammar"
    }
  ],
  "suggestions": [
    "建议1",
    "建议2"
  ],
  "strengths": [
    "优点1",
    "优点2"
  ],
  "weaknesses": [
    "需要改进的地方1",
    "需要改进的地方2"
  ]
}`, taskType, content)

	response, err := s.callOpenAI(ctx, prompt)
	if err != nil {
		return nil, err
	}

	// 解析JSON响应
	var correction model.WritingCorrection
	if err := json.Unmarshal([]byte(response), &correction); err != nil {
		// 如果JSON解析失败，返回基本的批改结果
		return &model.WritingCorrection{
			OverallScore: 75,
			Suggestions:  []string{"AI批改服务暂时不可用，请稍后重试"},
		}, nil
	}

	return &correction, nil
}

// EvaluateSpeaking 口语评估
func (s *aiService) EvaluateSpeaking(ctx context.Context, audioText string, prompt string) (*model.SpeakingEvaluation, error) {
	evalPrompt := fmt.Sprintf(`请对以下英语口语进行评估，题目：%s

口语内容：
%s

请按照以下JSON格式返回评估结果：
{
  "overall_score": 85,
  "pronunciation_score": 80,
  "fluency_score": 90,
  "grammar_score": 85,
  "vocabulary_score": 88,
  "feedback": "整体评价",
  "strengths": [
    "优点1",
    "优点2"
  ],
  "improvements": [
    "需要改进的地方1",
    "需要改进的地方2"
  ]
}`, prompt, audioText)

	response, err := s.callOpenAI(ctx, evalPrompt)
	if err != nil {
		return nil, err
	}

	// 解析JSON响应
	var evaluation model.SpeakingEvaluation
	if err := json.Unmarshal([]byte(response), &evaluation); err != nil {
		// 如果JSON解析失败，返回基本的评估结果
		return &model.SpeakingEvaluation{
			OverallScore: 75,
			Feedback:     "AI评估服务暂时不可用，请稍后重试",
		}, nil
	}

	return &evaluation, nil
}

// GetRecommendations 智能推荐
func (s *aiService) GetRecommendations(ctx context.Context, userLevel string, learningHistory []string) (*model.AIRecommendation, error) {
	historyStr := strings.Join(learningHistory, ", ")
	prompt := fmt.Sprintf(`基于用户的英语水平（%s）和学习历史（%s），请提供个性化的学习推荐。

请按照以下JSON格式返回推荐结果：
{
  "recommended_topics": [
    "推荐主题1",
    "推荐主题2"
  ],
  "difficulty_level": "intermediate",
  "study_plan": [
    "学习计划步骤1",
    "学习计划步骤2"
  ],
  "focus_areas": [
    "重点关注领域1",
    "重点关注领域2"
  ]
}`, userLevel, historyStr)

	response, err := s.callOpenAI(ctx, prompt)
	if err != nil {
		return nil, err
	}

	// 解析JSON响应
	var recommendation model.AIRecommendation
	if err := json.Unmarshal([]byte(response), &recommendation); err != nil {
		// 如果JSON解析失败，返回基本的推荐结果
		return &model.AIRecommendation{
			RecommendedTopics: []string{"基础语法练习", "日常对话练习"},
			DifficultyLevel:   "beginner",
			StudyPlan:        []string{"每天练习30分钟", "重点关注基础词汇"},
		}, nil
	}

	return &recommendation, nil
}

// GenerateExercise 生成练习题
func (s *aiService) GenerateExercise(ctx context.Context, content string, exerciseType string) (*model.Exercise, error) {
	prompt := fmt.Sprintf(`基于以下内容生成%s类型的练习题：

内容：
%s

请按照以下JSON格式返回练习题：
{
  "title": "练习题标题",
  "instructions": "练习说明",
  "questions": [
    {
      "question": "问题1",
      "options": ["选项A", "选项B", "选项C", "选项D"],
      "correct_answer": "正确答案",
      "explanation": "解释"
    }
  ]
}`, exerciseType, content)

	response, err := s.callOpenAI(ctx, prompt)
	if err != nil {
		return nil, err
	}

	// 解析JSON响应
	var exercise model.Exercise
	if err := json.Unmarshal([]byte(response), &exercise); err != nil {
		// 如果JSON解析失败，返回基本的练习题
		return &model.Exercise{
			Title:        "基础练习",
			Instructions: "AI练习生成服务暂时不可用，请稍后重试",
			Questions:    []model.Question{},
		}, nil
	}

	return &exercise, nil
}