import Combine
import Foundation

struct AIMessage: Identifiable {
    let id: UUID
    let role: AIMessageRole
    let content: String
    let thinkingContent: String?
    let citations: [ChatCitation]?
    let isStreaming: Bool

    init(role: AIMessageRole, content: String, thinkingContent: String? = nil, citations: [ChatCitation]? = nil, isStreaming: Bool = false, id: UUID = UUID()) {
        self.id = id
        self.role = role
        self.content = content
        self.thinkingContent = thinkingContent
        self.citations = citations
        self.isStreaming = isStreaming
    }
}

enum AIMessageRole {
    case user, ai
}

@MainActor
final class AIChatViewModel: ObservableObject {
    @Published var messages: [AIMessage] = []
    @Published var inputText = ""
    @Published var isSending = false
    @Published var isCreatingSession = false
    @Published var sessionError: String?

    private var sessionId: String?
    private var entryContext: ChatEntryContext?

    var canSend: Bool {
        !inputText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !isSending && sessionId != nil
    }

    var isReady: Bool { sessionId != nil }

    var scopeLabel: String? {
        guard let ctx = entryContext, ctx.scopeType != .global else { return nil }
        return "提问范围：\(ctx.scopeName)"
    }

    var sessionListFilter: (scopeType: String, scopeId: String)? {
        guard let ctx = entryContext, ctx.scopeType != .global, let sid = ctx.scopeId else { return nil }
        return (ctx.scopeType.rawValue, sid)
    }

    var scopeIcon: String {
        guard let ctx = entryContext else { return "globe" }
        switch ctx.scopeType {
        case .knowledgeBase: return "books.vertical"
        case .folder: return "folder"
        case .material: return "doc.text"
        case .knowledgeItem: return "lightbulb"
        case .global: return "globe"
        }
    }

    func load() async {
        guard sessionId == nil else { return }

        isCreatingSession = true

        let ctx = entryContext ?? ChatEntryContext(
            scopeType: .global,
            scopeId: nil,
            scopeName: "AI 对话",
            parentKnowledgeBaseId: nil,
            createdFrom: "global_ai_entry"
        )

        print("[AIChat] load() entry — scopeType=\(ctx.scopeType.rawValue), scopeId=\(ctx.scopeId ?? "nil"), parentKB=\(ctx.parentKnowledgeBaseId ?? "nil")")

        do {
            let session = try await RagChatService.shared.createSession(ctx: ctx)
            print("[AIChat] open-or-create OK — sessionId=\(session.id), isNew=\(session.createdAt == session.updatedAt)")
            await loadSession(session.id)
        } catch {
            print("[AIChat] open-or-create FAILED: \(error)")
            if let apiErr = error as? APIError {
                print("[AIChat] APIError detail: \(apiErr)")
            }
            sessionError = "创建对话失败: \(error.localizedDescription)"
            isCreatingSession = false
        }
    }

    func createNewSession() async {
        sessionId = nil
        messages = []
        isCreatingSession = true

        let ctx = entryContext ?? ChatEntryContext(
            scopeType: .global,
            scopeId: nil,
            scopeName: "AI 对话",
            parentKnowledgeBaseId: nil,
            createdFrom: "global_ai_entry"
        )

        print("[AIChat] createNewSession() — scopeType=\(ctx.scopeType.rawValue), scopeId=\(ctx.scopeId ?? "nil")")

        do {
            let session = try await RagChatService.shared.createSession(ctx: ctx, forceCreate: true)
            print("[AIChat] forceCreate OK — sessionId=\(session.id)")
            sessionId = session.id
            let scopeLabel = ctx.scopeType != .global ? "「\(ctx.scopeName)」的" : ""
            messages = [AIMessage(role: .ai, content: "你好！我是你的 AI 学习助手，基于\(scopeLabel)内容回答问题。")]
            isCreatingSession = false
        } catch {
            print("[AIChat] forceCreate FAILED: \(error)")
            sessionError = "创建对话失败: \(error.localizedDescription)"
            isCreatingSession = false
        }
    }

    func send() {
        guard canSend, let sid = sessionId else { return }
        let text = inputText.trimmingCharacters(in: .whitespacesAndNewlines)
        print("[AIChat] send — sessionId=\(sid), text=\(text.prefix(50))")
        messages.append(AIMessage(role: .user, content: text))
        inputText = ""
        isSending = true

        let placeholderId = UUID()
        messages.append(AIMessage(role: .ai, content: "", isStreaming: true, id: placeholderId))

        Task {
            do {
                let stream = RagChatService.shared.sendMessageStream(sessionId: sid, content: text)
                var thinking = ""
                var reply = ""

                for try await chunk in stream {
                    switch chunk.type {
                    case "thinking":
                        thinking += chunk.content ?? ""
                        if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
                            messages[idx] = AIMessage(role: .ai, content: reply, thinkingContent: thinking, isStreaming: true, id: placeholderId)
                        }
                    case "content":
                        reply += chunk.content ?? ""
                        if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
                            messages[idx] = AIMessage(role: .ai, content: reply, thinkingContent: thinking, isStreaming: true, id: placeholderId)
                        }
                    case "error":
                        print("[AIChat] stream error: \(chunk.content ?? "unknown")")
                        if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
                            messages[idx] = AIMessage(role: .ai, content: "请求失败: \(chunk.content ?? "未知错误")")
                        }
                    case "done":
                        print("[AIChat] stream done — reply=\(reply.count)chars, thinking=\(thinking.count)chars")
                        if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
                            messages[idx] = AIMessage(role: .ai, content: reply, thinkingContent: thinking.isEmpty ? nil : thinking)
                        }
                    default: break
                    }
                }
            } catch {
                print("[AIChat] stream FAILED: \(error)")
                if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
                    messages[idx] = AIMessage(role: .ai, content: "发送失败: \(error.localizedDescription)")
                }
            }
            isSending = false
        }
    }

    func setEntryContext(_ ctx: ChatEntryContext) { entryContext = ctx }

    func loadSession(_ id: String) async {
        sessionId = id
        isCreatingSession = true
        do {
            print("[AIChat] loadSession — id=\(id)")
            let msgs: [ChatMessage] = try await RagChatService.shared.getMessages(sessionId: id)
            print("[AIChat] loadSession OK — \(msgs.count) messages")

            // Update entryContext from the first message's scope snapshot (if available)
            if let snapshot = msgs.first?.scopeSnapshot,
               let scopeTypeStr = snapshot.scopeType,
               let scopeType = ChatScopeType(rawValue: scopeTypeStr) {
                entryContext = ChatEntryContext(
                    scopeType: scopeType,
                    scopeId: snapshot.scopeId,
                    scopeName: scopeLabel ?? "AI 对话",
                    parentKnowledgeBaseId: snapshot.parentKnowledgeBaseId,
                    createdFrom: "session_switch"
                )
            }

            let scopePrefix: String = {
                guard let ctx = entryContext, ctx.scopeType != .global else { return "" }
                return "「\(ctx.scopeName)」的"
            }()

            if msgs.isEmpty {
                messages = [AIMessage(role: .ai, content: "你好！我是你的 AI 学习助手，基于\(scopePrefix)内容回答问题。")]
            } else {
                messages = msgs.map { m in
                    AIMessage(role: m.role == "user" ? .user : .ai, content: m.content, citations: m.citations)
                }
            }
        } catch {
            print("[AIChat] loadSession FAILED: \(error)")
            sessionError = "加载对话失败: \(error.localizedDescription)"
        }
        isCreatingSession = false
    }
}
