import AppKit
import SwiftUI

/// Displays calculation results in a vertical column, one result per line,
/// aligned to match the corresponding editor lines.
/// Uses NSViewRepresentable wrapping NSScrollView + StripedTextView for
/// pixel-perfect line height alignment with the editor, including zebra striping.
struct AnswerColumnView: NSViewRepresentable {
    let results: [LineResult]
    @Binding var scrollOffset: CGFloat
    var font: NSFont
    var alignment: NSTextAlignment = .right

    func makeCoordinator() -> Coordinator {
        Coordinator()
    }

    func makeNSView(context: Context) -> NSScrollView {
        let scrollView = NSScrollView()
        scrollView.hasVerticalScroller = false
        scrollView.hasHorizontalScroller = false
        scrollView.borderType = .noBorder
        scrollView.drawsBackground = false
        // Disable user scrolling — scroll is driven by the editor
        scrollView.verticalScrollElasticity = .none
        scrollView.horizontalScrollElasticity = .none

        let textView = StripedTextView()
        textView.isEditable = false
        textView.isSelectable = true
        textView.isRichText = true
        textView.usesFontPanel = false
        textView.drawsBackground = true
        textView.backgroundColor = .clear

        // Match editor text container settings for alignment
        textView.textContainer?.lineFragmentPadding = 4
        textView.textContainerInset = NSSize(width: 8, height: 8)

        // Let the text container track the scroll view width
        textView.isHorizontallyResizable = false
        textView.textContainer?.widthTracksTextView = true
        textView.textContainer?.containerSize = NSSize(
            width: 0,
            height: CGFloat.greatestFiniteMagnitude
        )
        textView.maxSize = NSSize(
            width: CGFloat.greatestFiniteMagnitude,
            height: CGFloat.greatestFiniteMagnitude
        )

        scrollView.documentView = textView
        context.coordinator.textView = textView
        context.coordinator.scrollView = scrollView

        updateContent(textView: textView)
        return scrollView
    }

    func updateNSView(_ scrollView: NSScrollView, context: Context) {
        guard let textView = scrollView.documentView as? NSTextView else { return }

        updateContent(textView: textView)

        // Sync scroll position from editor
        let currentOffset = scrollView.contentView.bounds.origin.y
        if abs(currentOffset - scrollOffset) > 0.5 {
            scrollView.contentView.scroll(to: NSPoint(x: 0, y: scrollOffset))
            scrollView.reflectScrolledClipView(scrollView.contentView)
        }
    }

    private func updateContent(textView: NSTextView) {
        let attributedString = NSMutableAttributedString()

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = alignment

        let resultColor = NSColor.secondaryLabelColor
        let errorColor = NSColor.systemRed

        for (index, lineResult) in results.enumerated() {
            // Only show successful results — errors stay as underlines in the editor
            let displayText = lineResult.isError ? "" : (lineResult.result ?? "")
            let color = resultColor

            let attributes: [NSAttributedString.Key: Any] = [
                .font: font,
                .foregroundColor: color,
                .paragraphStyle: paragraphStyle,
            ]

            let line = NSAttributedString(string: displayText, attributes: attributes)
            attributedString.append(line)

            // Add newline between lines (but not after the last)
            if index < results.count - 1 {
                let newline = NSAttributedString(
                    string: "\n",
                    attributes: [.font: font]
                )
                attributedString.append(newline)
            }
        }

        textView.textStorage?.setAttributedString(attributedString)
    }

    final class Coordinator {
        weak var textView: NSTextView?
        weak var scrollView: NSScrollView?
    }
}
