import Cocoa

// MARK: - 记忆条目（与 memory.json 对应）

struct MemoryEntry: Codable, Identifiable {
    var id: String
    var type: String
    var content: String
    var keywords: [String]
    var createdAt: String
    var updatedAt: String

    enum CodingKeys: String, CodingKey {
        case id, type, content, keywords
        case createdAt = "created_at"
        case updatedAt = "updated_at"
    }

    var typeDisplayName: String {
        switch type {
        case "preference": return "偏好"
        case "habit": return "习惯"
        case "event": return "事件"
        case "todo": return "待办"
        case "identity": return "身份"
        case "relationship": return "关系"
        default: return "其他"
        }
    }

    var keywordsString: String {
        keywords.joined(separator: ", ")
    }

    var dateDisplay: String {
        String((updatedAt.isEmpty ? createdAt : updatedAt).prefix(10))
    }
}

// MARK: - 记忆管理窗口

final class MemoryWindow: NSWindow {

    private let searchField: NSTextField
    private let typeFilterPopup: NSPopUpButton
    private let tableView: NSTableView
    private let addButton: NSButton
    private let editButton: NSButton
    private let deleteButton: NSButton
    private let refreshButton: NSButton
    private let statusLabel: NSTextField

    private var allEntries: [MemoryEntry] = []
    private var filteredEntries: [MemoryEntry] = []

    private let memoryPath: String = {
        let appSupport = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
        return appSupport.appendingPathComponent("VoiceInput/memory/memory.json").path
    }()

    init() {
        searchField = NSTextField(frame: .zero)
        typeFilterPopup = NSPopUpButton(frame: .zero, pullsDown: false)
        tableView = NSTableView(frame: .zero)
        addButton = NSButton(title: "+", target: nil, action: nil)
        editButton = NSButton(title: "编辑", target: nil, action: nil)
        deleteButton = NSButton(title: "删除", target: nil, action: nil)
        refreshButton = NSButton(title: "刷新", target: nil, action: nil)
        statusLabel = NSTextField(labelWithString: "")

        let rect = NSRect(x: 0, y: 0, width: 680, height: 480)
        super.init(
            contentRect: rect,
            styleMask: [.titled, .closable, .miniaturizable, .resizable],
            backing: .buffered,
            defer: false
        )

        configureWindow()
        buildUI()
        loadMemories()
    }

    private func configureWindow() {
        title = "记忆管理"
        isReleasedWhenClosed = false
        center()
        minSize = NSSize(width: 520, height: 360)
    }

    override func makeKeyAndOrderFront(_ sender: Any?) {
        loadMemories()
        super.makeKeyAndOrderFront(sender)
    }

    // MARK: - 快捷键

    override func performKeyEquivalent(with event: NSEvent) -> Bool {
        guard event.modifierFlags.contains(.command) else {
            return super.performKeyEquivalent(with: event)
        }
        let selector: Selector?
        switch event.charactersIgnoringModifiers?.lowercased() {
        case "a": selector = #selector(NSText.selectAll(_:))
        case "c": selector = Selector(("copy:"))
        case "v": selector = Selector(("paste:"))
        case "x": selector = Selector(("cut:"))
        default: selector = nil
        }
        guard let sel = selector else {
            return super.performKeyEquivalent(with: event)
        }
        if NSApp.sendAction(sel, to: nil, from: self) { return true }
        return super.performKeyEquivalent(with: event)
    }

    private func makeLabel(_ text: String) -> NSTextField {
        let label = NSTextField(labelWithString: text)
        label.font = .systemFont(ofSize: 11, weight: .semibold)
        label.textColor = .secondaryLabelColor
        label.alignment = .right
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }

    private func buildUI() {
        guard let content = contentView else { return }

        // 搜索区域
        let searchLabel = makeLabel("搜索:")
        searchField.placeholderString = "输入关键词搜索记忆..."
        searchField.font = .systemFont(ofSize: 13)
        searchField.bezelStyle = .roundedBezel
        searchField.translatesAutoresizingMaskIntoConstraints = false
        searchField.target = self
        searchField.action = #selector(searchChanged)

        let filterLabel = makeLabel("类型:")
        typeFilterPopup.translatesAutoresizingMaskIntoConstraints = false
        typeFilterPopup.addItems(withTitles: ["全部", "偏好", "习惯", "事件", "待办", "身份", "关系", "其他"])
        typeFilterPopup.target = self
        typeFilterPopup.action = #selector(filterChanged)

        // 表格
        let scrollView = NSScrollView(frame: .zero)
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.hasVerticalScroller = true
        scrollView.borderType = .bezelBorder

        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.headerView = nil
        tableView.selectionHighlightStyle = .regular
        tableView.dataSource = self
        tableView.delegate = self
        tableView.rowHeight = 28
        tableView.intercellSpacing = NSSize(width: 4, height: 2)
        tableView.usesAlternatingRowBackgroundColors = true

        let colType = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("type"))
        colType.title = "类型"; colType.width = 50; colType.minWidth = 40
        let colContent = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("content"))
        colContent.title = "内容"; colContent.width = 280; colContent.minWidth = 150
        let colKeywords = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("keywords"))
        colKeywords.title = "关键词"; colKeywords.width = 140; colKeywords.minWidth = 80
        let colDate = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("date"))
        colDate.title = "更新时间"; colDate.width = 100; colDate.minWidth = 80

        tableView.addTableColumn(colType)
        tableView.addTableColumn(colContent)
        tableView.addTableColumn(colKeywords)
        tableView.addTableColumn(colDate)

        scrollView.documentView = tableView

        // 按钮
        addButton.bezelStyle = .rounded
        addButton.font = .systemFont(ofSize: 13, weight: .bold)
        addButton.translatesAutoresizingMaskIntoConstraints = false
        addButton.target = self
        addButton.action = #selector(addMemory)

        editButton.bezelStyle = .rounded
        editButton.translatesAutoresizingMaskIntoConstraints = false
        editButton.target = self
        editButton.action = #selector(editMemory)

        deleteButton.bezelStyle = .rounded
        deleteButton.translatesAutoresizingMaskIntoConstraints = false
        deleteButton.target = self
        deleteButton.action = #selector(deleteMemory)

        refreshButton.bezelStyle = .rounded
        refreshButton.translatesAutoresizingMaskIntoConstraints = false
        refreshButton.target = self
        refreshButton.action = #selector(refreshMemories)

        let buttonStack = NSStackView(views: [addButton, editButton, deleteButton, refreshButton])
        buttonStack.translatesAutoresizingMaskIntoConstraints = false
        buttonStack.orientation = .horizontal
        buttonStack.spacing = 8

        statusLabel.font = .systemFont(ofSize: 11)
        statusLabel.textColor = .secondaryLabelColor
        statusLabel.alignment = .center
        statusLabel.translatesAutoresizingMaskIntoConstraints = false

        content.addSubview(searchLabel)
        content.addSubview(searchField)
        content.addSubview(filterLabel)
        content.addSubview(typeFilterPopup)
        content.addSubview(scrollView)
        content.addSubview(buttonStack)
        content.addSubview(statusLabel)

        NSLayoutConstraint.activate([
            searchLabel.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 20),
            searchLabel.topAnchor.constraint(equalTo: content.topAnchor, constant: 20),
            searchLabel.widthAnchor.constraint(equalToConstant: 40),

            searchField.leadingAnchor.constraint(equalTo: searchLabel.trailingAnchor, constant: 6),
            searchField.centerYAnchor.constraint(equalTo: searchLabel.centerYAnchor),
            searchField.widthAnchor.constraint(equalToConstant: 240),

            filterLabel.leadingAnchor.constraint(equalTo: searchField.trailingAnchor, constant: 16),
            filterLabel.centerYAnchor.constraint(equalTo: searchLabel.centerYAnchor),
            filterLabel.widthAnchor.constraint(equalToConstant: 40),

            typeFilterPopup.leadingAnchor.constraint(equalTo: filterLabel.trailingAnchor, constant: 6),
            typeFilterPopup.centerYAnchor.constraint(equalTo: searchLabel.centerYAnchor),
            typeFilterPopup.widthAnchor.constraint(equalToConstant: 100),

            scrollView.topAnchor.constraint(equalTo: searchField.bottomAnchor, constant: 14),
            scrollView.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 20),
            scrollView.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -20),
            scrollView.bottomAnchor.constraint(equalTo: buttonStack.topAnchor, constant: -10),

            buttonStack.centerXAnchor.constraint(equalTo: content.centerXAnchor),
            buttonStack.bottomAnchor.constraint(equalTo: statusLabel.topAnchor, constant: -8),

            statusLabel.centerXAnchor.constraint(equalTo: content.centerXAnchor),
            statusLabel.bottomAnchor.constraint(equalTo: content.bottomAnchor, constant: -16),
            statusLabel.widthAnchor.constraint(equalToConstant: 640)
        ])
    }

    // MARK: - 数据加载/保存

    private func loadMemories() {
        guard let data = try? Data(contentsOf: URL(fileURLWithPath: memoryPath)) else {
            allEntries = []
            applyFilter()
            return
        }
        let decoder = JSONDecoder()
        if let entries = try? decoder.decode([MemoryEntry].self, from: data) {
            allEntries = entries.sorted { $0.updatedAt > $1.updatedAt }
        } else {
            allEntries = []
        }
        applyFilter()
    }

    private func saveMemories() {
        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        guard let data = try? encoder.encode(allEntries) else { return }
        let dir = (memoryPath as NSString).deletingLastPathComponent
        if !FileManager.default.fileExists(atPath: dir) {
            try? FileManager.default.createDirectory(atPath: dir, withIntermediateDirectories: true)
        }
        try? data.write(to: URL(fileURLWithPath: memoryPath), options: .atomic)
    }

    // MARK: - 过滤

    private func applyFilter() {
        let query = searchField.stringValue.trimmingCharacters(in: .whitespaces).lowercased()
        let typeIndex = typeFilterPopup.indexOfSelectedItem
        let typeMap = ["preference", "habit", "event", "todo", "identity", "relationship", "other"]

        filteredEntries = allEntries.filter { entry in
            if typeIndex > 0 && typeIndex <= typeMap.count {
                if entry.type != typeMap[typeIndex - 1] { return false }
            }
            if !query.isEmpty {
                let matchContent = entry.content.lowercased().contains(query)
                let matchKeywords = entry.keywords.contains { $0.lowercased().contains(query) }
                if !matchContent && !matchKeywords { return false }
            }
            return true
        }
        tableView.reloadData()
        statusLabel.stringValue = "共 \(filteredEntries.count) 条记忆"
    }

    @objc private func searchChanged() { applyFilter() }
    @objc private func filterChanged() { applyFilter() }

    // MARK: - 操作

    @objc private func addMemory() {
        showEditor(for: nil)
    }

    @objc private func editMemory() {
        let row = tableView.selectedRow
        guard row >= 0, row < filteredEntries.count else {
            statusLabel.stringValue = "请先选择一条记忆"
            return
        }
        showEditor(for: filteredEntries[row])
    }

    @objc private func deleteMemory() {
        let row = tableView.selectedRow
        guard row >= 0, row < filteredEntries.count else {
            statusLabel.stringValue = "请先选择一条记忆"
            return
        }
        let entry = filteredEntries[row]
        let alert = NSAlert()
        alert.messageText = "删除记忆"
        alert.informativeText = "确定要删除「\(String(entry.content.prefix(50)))」吗？"
        alert.alertStyle = .warning
        alert.addButton(withTitle: "删除")
        alert.addButton(withTitle: "取消")
        if alert.runModal() == .alertFirstButtonReturn {
            allEntries.removeAll { $0.id == entry.id }
            saveMemories()
            applyFilter()
            statusLabel.stringValue = "已删除"
        }
    }

    @objc private func refreshMemories() {
        loadMemories()
        statusLabel.stringValue = "已刷新，共 \(filteredEntries.count) 条记忆"
        statusLabel.textColor = .systemGreen
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in
            self?.statusLabel.stringValue = "共 \(self?.filteredEntries.count ?? 0) 条记忆"
            self?.statusLabel.textColor = .secondaryLabelColor
        }
    }

    // MARK: - 编辑器

    private func showEditor(for entry: MemoryEntry?) {
        let isEdit = entry != nil
        let panel = NSPanel(
            contentRect: NSRect(x: 0, y: 0, width: 420, height: 300),
            styleMask: [.titled, .closable],
            backing: .buffered,
            defer: false
        )
        panel.title = isEdit ? "编辑记忆" : "添加记忆"
        panel.isReleasedWhenClosed = false
        panel.center()

        guard let contentView = panel.contentView else { return }

        let typeLabel = makeLabel("类型:")
        let typePopup = NSPopUpButton(frame: .zero, pullsDown: false)
        typePopup.translatesAutoresizingMaskIntoConstraints = false
        typePopup.addItems(withTitles: ["偏好", "习惯", "事件", "待办", "身份", "关系", "其他"])
        let typeMap = ["preference", "habit", "event", "todo", "identity", "relationship", "other"]
        if let e = entry, let idx = typeMap.firstIndex(of: e.type) {
            typePopup.selectItem(at: idx)
        }

        let contentLabel = makeLabel("内容:")
        let contentField = NSTextField(frame: .zero)
        contentField.placeholderString = "记忆内容..."
        contentField.stringValue = entry?.content ?? ""
        contentField.font = .systemFont(ofSize: 13)
        contentField.bezelStyle = .roundedBezel
        contentField.translatesAutoresizingMaskIntoConstraints = false

        let keywordsLabel = makeLabel("关键词:")
        let keywordsField = NSTextField(frame: .zero)
        keywordsField.placeholderString = "用逗号分隔，如：咖啡, 美式"
        keywordsField.stringValue = entry?.keywords.joined(separator: ", ") ?? ""
        keywordsField.font = .systemFont(ofSize: 13)
        keywordsField.bezelStyle = .roundedBezel
        keywordsField.translatesAutoresizingMaskIntoConstraints = false

        let saveBtn = NSButton(title: isEdit ? "保存" : "添加", target: nil, action: nil)
        saveBtn.bezelStyle = .rounded
        saveBtn.translatesAutoresizingMaskIntoConstraints = false
        saveBtn.keyEquivalent = "\r"

        let cancelBtn = NSButton(title: "取消", target: nil, action: nil)
        cancelBtn.bezelStyle = .rounded
        cancelBtn.translatesAutoresizingMaskIntoConstraints = false

        let btnStack = NSStackView(views: [cancelBtn, saveBtn])
        btnStack.translatesAutoresizingMaskIntoConstraints = false
        btnStack.orientation = .horizontal
        btnStack.spacing = 12
        btnStack.distribution = .fillEqually

        contentView.addSubview(typeLabel)
        contentView.addSubview(typePopup)
        contentView.addSubview(contentLabel)
        contentView.addSubview(contentField)
        contentView.addSubview(keywordsLabel)
        contentView.addSubview(keywordsField)
        contentView.addSubview(btnStack)

        NSLayoutConstraint.activate([
            typeLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            typeLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 24),
            typeLabel.widthAnchor.constraint(equalToConstant: 60),
            typePopup.leadingAnchor.constraint(equalTo: typeLabel.trailingAnchor, constant: 8),
            typePopup.centerYAnchor.constraint(equalTo: typeLabel.centerYAnchor),
            typePopup.widthAnchor.constraint(equalToConstant: 160),

            contentLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            contentLabel.topAnchor.constraint(equalTo: typeLabel.bottomAnchor, constant: 18),
            contentLabel.widthAnchor.constraint(equalToConstant: 60),
            contentField.leadingAnchor.constraint(equalTo: contentLabel.trailingAnchor, constant: 8),
            contentField.centerYAnchor.constraint(equalTo: contentLabel.centerYAnchor),
            contentField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),

            keywordsLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            keywordsLabel.topAnchor.constraint(equalTo: contentLabel.bottomAnchor, constant: 18),
            keywordsLabel.widthAnchor.constraint(equalToConstant: 60),
            keywordsField.leadingAnchor.constraint(equalTo: keywordsLabel.trailingAnchor, constant: 8),
            keywordsField.centerYAnchor.constraint(equalTo: keywordsLabel.centerYAnchor),
            keywordsField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),

            btnStack.topAnchor.constraint(equalTo: keywordsLabel.bottomAnchor, constant: 22),
            btnStack.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            btnStack.widthAnchor.constraint(equalToConstant: 200)
        ])

        // 保存/取消动作
        let saveAction = { [weak self] in
            guard let self = self else { return }
            let typeIdx = typePopup.indexOfSelectedItem
            guard typeIdx >= 0, typeIdx < typeMap.count else { return }
            let selectedType = typeMap[typeIdx]
            let newContent = contentField.stringValue.trimmingCharacters(in: .whitespaces)
            guard !newContent.isEmpty else { return }
            let keywords = keywordsField.stringValue
                .components(separatedBy: ",")
                .map { $0.trimmingCharacters(in: .whitespaces) }
                .filter { !$0.isEmpty }
            let now = ISO8601DateFormatter().string(from: Date())

            if let e = entry {
                if let idx = self.allEntries.firstIndex(where: { $0.id == e.id }) {
                    self.allEntries[idx].type = selectedType
                    self.allEntries[idx].content = newContent
                    self.allEntries[idx].keywords = keywords
                    self.allEntries[idx].updatedAt = now
                }
            } else {
                let newId = UUID().uuidString.prefix(8).lowercased()
                let newEntry = MemoryEntry(
                    id: String(newId), type: selectedType, content: newContent,
                    keywords: keywords, createdAt: now, updatedAt: now
                )
                self.allEntries.append(newEntry)
            }
            self.saveMemories()
            self.applyFilter()
            self.statusLabel.stringValue = isEdit ? "已更新" : "已添加"
            self.statusLabel.textColor = .systemGreen
            panel.close()
        }

        // 使用 helper 类绑定 action
        let helper = MemoryEditorHelper(panel: panel, onSave: saveAction)
        saveBtn.target = helper
        saveBtn.action = #selector(MemoryEditorHelper.saveAction)
        cancelBtn.target = helper
        cancelBtn.action = #selector(MemoryEditorHelper.cancelAction)
        objc_setAssociatedObject(saveBtn, "helper", helper, .OBJC_ASSOCIATION_RETAIN)
        objc_setAssociatedObject(cancelBtn, "helper", helper, .OBJC_ASSOCIATION_RETAIN)

        panel.makeKeyAndOrderFront(nil)
    }
}

// MARK: - NSTableView

extension MemoryWindow: NSTableViewDataSource {
    func numberOfRows(in tableView: NSTableView) -> Int { filteredEntries.count }
}

extension MemoryWindow: NSTableViewDelegate {
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        guard row < filteredEntries.count, let column = tableColumn else { return nil }
        let entry = filteredEntries[row]
        let textField: NSTextField
        if let reused = tableView.makeView(withIdentifier: column.identifier, owner: nil) as? NSTextField {
            textField = reused
        } else {
            textField = NSTextField(labelWithString: "")
            textField.identifier = column.identifier
            textField.font = .systemFont(ofSize: 12)
            textField.lineBreakMode = .byTruncatingTail
            textField.maximumNumberOfLines = 1
        }
        switch column.identifier.rawValue {
        case "type": textField.stringValue = entry.typeDisplayName
        case "content": textField.stringValue = entry.content
        case "keywords": textField.stringValue = entry.keywordsString
        case "date": textField.stringValue = entry.dateDisplay
        default: textField.stringValue = ""
        }
        return textField
    }
}

// MARK: - 编辑器 Helper

private class MemoryEditorHelper: NSObject {
    weak var panel: NSPanel?
    let onSave: () -> Void

    init(panel: NSPanel, onSave: @escaping () -> Void) {
        self.panel = panel
        self.onSave = onSave
    }

    @objc func saveAction() { onSave() }
    @objc func cancelAction() { panel?.close() }
}
