package service

import (
	"errors"
	"strings"
	"time"

	"github.com/2930134478/AI-CS/backend/models"
	"github.com/2930134478/AI-CS/backend/repository"
	"gorm.io/gorm"
)

// ConversationService 负责会话领域的业务编排。
type ConversationService struct {
	conversations *repository.ConversationRepository
	messages      *repository.MessageRepository
	aiConfigRepo  *repository.AIConfigRepository // 用于验证 AI 配置
	userRepo      *repository.UserRepository     // 用于查询用户设置
	systemLogSvc  *SystemLogService              // 可选，结构化日志
}

// CloseConversation 客服主动关闭会话（visitor/internal 通用）。
func (s *ConversationService) CloseConversation(conversationID uint, userID uint) error {
	if conversationID == 0 {
		return errors.New("conversation_id is required")
	}
	conv, err := s.conversations.GetByID(conversationID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return ErrConversationNotFound
		}
		return err
	}
	// internal 会话仅允许本人关闭；visitor 会话允许任意客服关闭（你们目前没有租户/组织概念）
	if conv.ConversationType == "internal" && userID > 0 && conv.AgentID != userID {
		return errors.New("权限不足：只能关闭自己的内部对话")
	}
	if conv.Status == "closed" {
		return nil
	}
	return s.conversations.UpdateFields(conversationID, map[string]interface{}{
		"status": "closed",
	})
}

// NewConversationService 创建 ConversationService 实例。
func NewConversationService(
	conversations *repository.ConversationRepository,
	messages *repository.MessageRepository,
	aiConfigRepo *repository.AIConfigRepository,
	userRepo *repository.UserRepository,
	systemLogSvc *SystemLogService,
) *ConversationService {
	return &ConversationService{
		conversations: conversations,
		messages:      messages,
		aiConfigRepo:  aiConfigRepo,
		userRepo:      userRepo,
		systemLogSvc:  systemLogSvc,
	}
}

// InitConversation 为访客创建或恢复会话。
func (s *ConversationService) InitConversation(input InitConversationInput) (*InitConversationResult, error) {
	var (
		conv *models.Conversation
		err  error
	)

	conv, err = s.conversations.FindOpenByVisitorID(input.VisitorID)
	isNewConversation := false

	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			now := time.Now()
			chatMode := input.ChatMode
			if chatMode == "" {
				chatMode = "human" // 默认人工客服
			}

			// 如果是 AI 模式，验证 AI 配置
			var aiConfigID *uint
			if chatMode == "ai" {
				if input.AIConfigID == nil || *input.AIConfigID == 0 {
					return nil, errors.New("AI 模式需要选择模型配置")
				}
				// 验证配置是否存在且开放
				config, err := s.aiConfigRepo.GetByID(*input.AIConfigID)
				if err != nil {
					return nil, errors.New("模型配置不存在")
				}
				if !config.IsPublic {
					return nil, errors.New("该模型未开放给访客使用")
				}
				if !config.IsActive {
					return nil, errors.New("该模型配置已禁用")
				}
				aiConfigID = input.AIConfigID
			}

			conv = &models.Conversation{
				ConversationType: "visitor",
				VisitorID:        input.VisitorID,
				Status:           "open",
				Website:          input.Website,
				Referrer:   input.Referrer,
				Browser:    input.Browser,
				OS:         input.OS,
				Language:   input.Language,
				IPAddress:  input.IPAddress,
				LastSeenAt: &now,
				ChatMode:   chatMode,
				AIConfigID: aiConfigID,
			}
			if err := s.conversations.Create(conv); err != nil {
				return nil, err
			}
			if s.systemLogSvc != nil {
				_ = s.systemLogSvc.Create(CreateSystemLogInput{
					Level:    "info",
					Category: "business",
					Event:    "conversation_created",
					Source:   "backend",
					Message:  "访客会话已创建",
					ConversationID: &conv.ID,
					VisitorID:      &input.VisitorID,
					Meta: map[string]interface{}{
						"chat_mode": conv.ChatMode,
						"ai_config": conv.AIConfigID,
					},
				})
			}
			isNewConversation = true
		} else {
			return nil, err
		}
	} else {
		// 恢复已存在的对话
		now := time.Now()
		updates := map[string]interface{}{
			"last_seen_at": &now,
		}

		// 更新访客信息（如果之前没有）
		if input.Website != "" && conv.Website == "" {
			updates["website"] = input.Website
		}
		if input.Referrer != "" && conv.Referrer == "" {
			updates["referrer"] = input.Referrer
		}
		if input.Browser != "" && conv.Browser == "" {
			updates["browser"] = input.Browser
		}
		if input.OS != "" && conv.OS == "" {
			updates["os"] = input.OS
		}
		if input.Language != "" && conv.Language == "" {
			updates["language"] = input.Language
		}
		if input.IPAddress != "" && conv.IPAddress == "" {
			updates["ip_address"] = input.IPAddress
		}

		// 重要：如果用户选择了新的 ChatMode，更新对话模式
		// 这样访客可以在人工客服和 AI 客服之间切换
		if input.ChatMode != "" && input.ChatMode != conv.ChatMode {
			chatMode := input.ChatMode
			oldMode := conv.ChatMode
			updates["chat_mode"] = chatMode

			// 如果是 AI 模式，验证并更新 AI 配置
			if chatMode == "ai" {
				if input.AIConfigID == nil || *input.AIConfigID == 0 {
					return nil, errors.New("AI 模式需要选择模型配置")
				}
				// 验证配置是否存在且开放
				config, err := s.aiConfigRepo.GetByID(*input.AIConfigID)
				if err != nil {
					return nil, errors.New("模型配置不存在")
				}
				if !config.IsPublic {
					return nil, errors.New("该模型未开放给访客使用")
				}
				if !config.IsActive {
					return nil, errors.New("该模型配置已禁用")
				}
				updates["ai_config_id"] = input.AIConfigID
			} else {
				// 切换到人工客服模式，清除 AI 配置
				updates["ai_config_id"] = nil
			}
			if s.systemLogSvc != nil {
				convID := conv.ID
				visitorID := conv.VisitorID
				_ = s.systemLogSvc.Create(CreateSystemLogInput{
					Level:          "info",
					Category:       "business",
					Event:          "conversation_mode_switch",
					Source:         "backend",
					ConversationID: &convID,
					VisitorID:      &visitorID,
					Message:        "会话模式切换",
					Meta: map[string]interface{}{
						"from": oldMode,
						"to":   chatMode,
					},
				})
			}
		}

		// 已在 AI 模式时，若用户在下拉中切换了模型（对话↔绘画），也要更新 ai_config_id
		if input.ChatMode == "ai" && conv.ChatMode == "ai" && input.AIConfigID != nil && *input.AIConfigID != 0 {
			if conv.AIConfigID == nil || *conv.AIConfigID != *input.AIConfigID {
				config, err := s.aiConfigRepo.GetByID(*input.AIConfigID)
				if err != nil {
					return nil, errors.New("模型配置不存在")
				}
				if !config.IsPublic {
					return nil, errors.New("该模型未开放给访客使用")
				}
				if !config.IsActive {
					return nil, errors.New("该模型配置已禁用")
				}
				updates["ai_config_id"] = input.AIConfigID
			}
		}

		if err := s.conversations.UpdateFields(conv.ID, updates); err != nil {
			return nil, err
		}

		// 重新获取更新后的对话信息
		conv, err = s.conversations.GetByID(conv.ID)
		if err != nil {
			return nil, err
		}
	}

	if isNewConversation {
		now := time.Now()
		chatMode := input.ChatMode
		if chatMode == "" {
			chatMode = "human" // 默认人工模式
		}
		message := &models.Message{
			ConversationID: conv.ID,
			SenderID:       0,
			SenderIsAgent:  false,
			Content:        "Visitor opened the page",
			MessageType:    "system_message",
			ChatMode:       chatMode, // 记录系统消息发送时的对话模式
			IsRead:         true,
			ReadAt:         &now,
		}
		if input.Website != "" {
			message.Content += " [" + input.Website + "]"
		}
		if err := s.messages.Create(message); err != nil {
			return nil, err
		}

		if input.Referrer != "" {
			readTime := time.Now()
			chatMode := input.ChatMode
			if chatMode == "" {
				chatMode = "human" // 默认人工模式
			}
			referrerMsg := &models.Message{
				ConversationID: conv.ID,
				SenderID:       0,
				SenderIsAgent:  false,
				Content:        "Visitor came from [" + input.Referrer + "]",
				MessageType:    "system_message",
				ChatMode:       chatMode, // 记录系统消息发送时的对话模式
				IsRead:         true,
				ReadAt:         &readTime,
			}
			if err := s.messages.Create(referrerMsg); err != nil {
				return nil, err
			}
		}
	}

	return &InitConversationResult{
		ConversationID: conv.ID,
		Status:         conv.Status,
	}, nil
}

// UpdateConversationContact 更新访客的联系信息（邮箱、电话、备注）。
func (s *ConversationService) UpdateConversationContact(input UpdateConversationContactInput) (*ConversationDetail, error) {
	if _, err := s.conversations.GetByID(input.ConversationID); err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, ErrConversationNotFound
		}
		return nil, err
	}

	updates := map[string]interface{}{}

	if input.Email != nil {
		updates["email"] = strings.TrimSpace(*input.Email)
	}
	if input.Phone != nil {
		updates["phone"] = strings.TrimSpace(*input.Phone)
	}
	if input.Notes != nil {
		updates["notes"] = strings.TrimSpace(*input.Notes)
	}

	if err := s.conversations.UpdateFields(input.ConversationID, updates); err != nil {
		return nil, err
	}

	// UpdateConversationContact 不传递 userID，因为更新联系信息时不需要检查参与状态
	return s.GetConversationDetail(input.ConversationID, 0)
}

func (s *ConversationService) buildSummary(conv models.Conversation, userID uint) (ConversationSummary, error) {
	var lastSeen *time.Time
	if conv.LastSeenAt != nil {
		lastSeen = conv.LastSeenAt
	}

	// 检查当前用户是否参与过该会话（是否发送过消息）
	hasParticipated := false
	if userID > 0 {
		if participated, err := s.messages.HasAgentParticipated(conv.ID, userID); err == nil {
			hasParticipated = participated
		}
		// 错误时静默处理，不影响流程
	}

	summary := ConversationSummary{
		ID:               conv.ID,
		ConversationType: conv.ConversationType,
		VisitorID:        conv.VisitorID,
		AgentID:           conv.AgentID,
		Status:            conv.Status,
		ChatMode:          conv.ChatMode,
		CreatedAt:         conv.CreatedAt,
		UpdatedAt:         conv.UpdatedAt,
		LastSeenAt:        lastSeen,
		HasParticipated:   hasParticipated,
	}

	if message, err := s.messages.LatestByConversationID(conv.ID); err == nil && message != nil {
		var readAt *time.Time
		if message.ReadAt != nil {
			readAt = message.ReadAt
		}
		summary.LastMessage = &LastMessageSummary{
			ID:            message.ID,
			Content:       message.Content,
			SenderIsAgent: message.SenderIsAgent,
			MessageType:   message.MessageType,
			IsRead:        message.IsRead,
			ReadAt:        readAt,
			CreatedAt:     message.CreatedAt,
		}
	}

	if count, err := s.messages.CountUnreadBySender(conv.ID, false); err == nil {
		summary.UnreadCount = count
	}

	return summary, nil
}

// ListConversations 返回当前活跃会话的摘要信息。
// userID: 当前登录的客服ID（可选，如果为0则使用默认过滤规则）
// 过滤规则：
// 1. 默认不显示 ChatMode == "ai" 的对话
// 2. 如果 userID > 0 且该用户的 ReceiveAIConversations == false，则不显示 AI 对话
// 3. 只显示 ChatMode == "human" 且存在访客消息的对话（访客切换到人工并发送消息后）
func (s *ConversationService) ListConversations(userID uint, status string) ([]ConversationSummary, error) {
	// 默认展示进行中（open）；历史使用 status=closed
	if status == "" {
		status = "open"
	}
	conversations, err := s.conversations.ListByTypeAndStatus("visitor", status)
	if err != nil {
		return nil, err
	}

	result := make([]ConversationSummary, 0, len(conversations))
	for _, conv := range conversations {
		// 过滤规则 1: 默认不显示 AI 对话
		// 只有在会话页面手动开启"显示 AI 对话"时才显示
		if conv.ChatMode == "ai" {
			continue
		}

		// 过滤规则 2: 如果是人工对话，检查是否有访客发送的消息
		// 只有当访客切换到人工并发送消息后，才显示在列表中
		if conv.ChatMode == "human" {
			hasVisitorMessage, err := s.messages.HasVisitorMessageInHumanMode(conv.ID)
			if err != nil {
				// 如果查询失败，为了安全起见，不显示该对话
				continue
			}
			if !hasVisitorMessage {
				// 没有访客消息，不显示（访客只是切换了模式，但还没发送消息）
				continue
			}
		}

		// 通过过滤，添加到结果列表
		summary, err := s.buildSummary(conv, userID)
		if err != nil {
			continue // 如果构建摘要失败，跳过该对话
		}
		result = append(result, summary)
	}
	return result, nil
}

// GetConversationDetail 获取指定会话的详细信息。内部对话仅创建者（agent_id）可查看。
func (s *ConversationService) GetConversationDetail(id uint, userID uint) (*ConversationDetail, error) {
	conv, err := s.conversations.GetByID(id)
	if err != nil {
		return nil, err
	}
	if conv.ConversationType == "internal" && userID > 0 && conv.AgentID != userID {
		return nil, gorm.ErrRecordNotFound
	}

	summary, err := s.buildSummary(*conv, userID)
	if err != nil {
		return nil, err
	}

	var lastSeen *time.Time
	if conv.LastSeenAt != nil {
		lastSeen = conv.LastSeenAt
	}

	return &ConversationDetail{
		ConversationSummary: summary,
		Website:             conv.Website,
		Referrer:            conv.Referrer,
		Browser:             conv.Browser,
		OS:                  conv.OS,
		Language:            conv.Language,
		IPAddress:           conv.IPAddress,
		Location:            conv.Location,
		Email:               conv.Email,
		Phone:               conv.Phone,
		Notes:               conv.Notes,
		LastSeen:            lastSeen,
	}, nil
}

// SearchConversations 根据关键字检索会话摘要。
// userID: 当前登录的客服ID（可选，用于检查参与状态）
func (s *ConversationService) SearchConversations(query string, userID uint, status string) ([]ConversationSummary, error) {
	pattern := "%" + query + "%"

	idSet := map[uint]struct{}{}

	if ids, err := s.messages.FindConversationIDsByContent(pattern); err == nil {
		for _, id := range ids {
			idSet[id] = struct{}{}
		}
	} else {
		return nil, err
	}

	if convs, err := s.conversations.SearchByIDOrVisitorLike(pattern); err == nil {
		for _, conv := range convs {
			idSet[conv.ID] = struct{}{}
		}
	} else {
		return nil, err
	}

	if len(idSet) == 0 {
		return []ConversationSummary{}, nil
	}

	ids := make([]uint, 0, len(idSet))
	for id := range idSet {
		ids = append(ids, id)
	}

	conversations, err := s.conversations.ListByIDs(ids)
	if err != nil {
		return nil, err
	}

	result := make([]ConversationSummary, 0, len(conversations))
	for _, conv := range conversations {
		if status != "" && status != "all" && conv.Status != status {
			continue
		}
		summary, err := s.buildSummary(conv, userID)
		if err != nil {
			return nil, err
		}
		result = append(result, summary)
	}
	return result, nil
}

// UpdateVisitorOnlineStatus 更新访客在线状态和最后活跃时间。
// 当 isOnline 为 true 时，更新 last_seen_at 为当前时间，并确保状态为 "open"。
// 当 isOnline 为 false 时，仅更新 last_seen_at 为当前时间，不改变状态。
func (s *ConversationService) UpdateVisitorOnlineStatus(conversationID uint, isOnline bool) error {
	now := time.Now()
	updates := map[string]interface{}{
		"last_seen_at": &now,
	}

	// 如果标记为在线，确保状态为 "open"（但不要将已关闭的会话重新打开）
	if isOnline {
		conv, err := s.conversations.GetByID(conversationID)
		if err != nil {
			return err
		}
		// 只有当前状态不是 "closed" 时，才更新为 "open"
		if conv.Status != "closed" {
			updates["status"] = "open"
		}
	}

	return s.conversations.UpdateFields(conversationID, updates)
}

// UpdateLastSeenAt 更新访客的最后活跃时间。
func (s *ConversationService) UpdateLastSeenAt(conversationID uint) error {
	now := time.Now()
	return s.conversations.UpdateFields(conversationID, map[string]interface{}{
		"last_seen_at": &now,
	})
}

// InitInternalConversation 为客服创建一条新的内部对话（知识库测试用）。每次调用创建新会话。
func (s *ConversationService) InitInternalConversation(agentID uint) (*InitConversationResult, error) {
	if agentID == 0 {
		return nil, errors.New("agent_id is required for internal conversation")
	}
	conv := &models.Conversation{
		ConversationType: "internal",
		VisitorID:        0,
		AgentID:          agentID,
		Status:           "open",
		ChatMode:         "ai",
	}
	if err := s.conversations.Create(conv); err != nil {
		return nil, err
	}
	return &InitConversationResult{
		ConversationID: conv.ID,
		Status:         conv.Status,
	}, nil
}

// ListInternalConversations 返回当前客服的全部内部对话（知识库测试用）。
func (s *ConversationService) ListInternalConversations(agentID uint, status string) ([]ConversationSummary, error) {
	if agentID == 0 {
		return []ConversationSummary{}, nil
	}
	if status == "" {
		status = "open"
	}
	conversations, err := s.conversations.ListInternalByAgentIDAndStatus(agentID, status)
	if err != nil {
		return nil, err
	}
	result := make([]ConversationSummary, 0, len(conversations))
	for _, conv := range conversations {
		summary, err := s.buildSummary(conv, agentID)
		if err != nil {
			continue
		}
		result = append(result, summary)
	}
	return result, nil
}
