import AppKit
import Foundation

// MARK: - Copy Link's pasteboard seam

/// The pasteboard Board ▸ Copy Link and the card context menu's own Copy Link row write through —
/// shared by both so the two surfaces can never come to carry different bytes (`BoardStore.copyCardLink`,
/// `CardFaceView.copyLink`).
///
/// Design ruling (2026-08-09, card 737a949f "Add an option to card context menu to copy a link to
/// the card folder"): "writes the card FOLDER's `file://` URL to the general pasteboard in one write
/// with two representations: file URL and plain absolute-path string, so Finder-aware surfaces get
/// the URL and terminals/editors get the path."
///
/// A protocol rather than a bare `NSPasteboard` call, for `ClipboardPasteboard`'s exact reason
/// (`ClipboardManifest.swift`): this write is a one-off outbound action — never a participant in
/// `ClipboardStore`'s cut/copy/paste cycle, so it needs no `changeCount` and no takeover detection —
/// but a test still has to read back what was written without racing the machine's one real
/// pasteboard, or every other test in the run.
@MainActor
protocol FolderLinkPasteboard: AnyObject {
    func write(fileURL: URL, path: String)
}

extension FolderLinkPasteboard {

    /// The one call both Copy Link surfaces make: a card folder's URL and the plain path derived
    /// from that very same URL, never two separately-resolved strings that could disagree.
    func write(link folder: URL) {
        write(fileURL: folder, path: folder.path)
    }
}

/// The real pasteboard — `NSPasteboard.general`, the ruling's own words.
///
/// **One `NSPasteboardItem` carrying both representations** — `SystemPasteboard.write(manifest:text:)`'s
/// own shape (`ClipboardManifest.swift`) — rather than two separate items, so a paste target sees one
/// clipboard entry and reads whichever flavor it understands: `.fileURL` for Finder-aware surfaces
/// (open panels, other apps that resolve dropped/pasted files), `.string` for terminals and editors
/// that only understand text and want the plain absolute path rather than a `file://` string.
@MainActor
final class SystemFolderLinkPasteboard: FolderLinkPasteboard {

    private let pasteboard: NSPasteboard

    init(_ pasteboard: NSPasteboard = .general) {
        self.pasteboard = pasteboard
    }

    func write(fileURL: URL, path: String) {
        pasteboard.clearContents()
        let item = NSPasteboardItem()
        item.setString(fileURL.absoluteString, forType: .fileURL)
        item.setString(path, forType: .string)
        pasteboard.writeObjects([item])
    }
}
