import Foundation

/// Send an email via Mail.app using AppleScript.
///
/// Mail.app was chosen as the send path (vs. direct SMTP) because:
/// - Mail.app is already authenticated with the Apple ID — no credentials need to be stored.
/// - The `send` AppleScript command is simple and well-tested on macOS.
/// - Any outbound message appears in the Sent folder automatically, maintaining a consistent
///   mail history without additional server-side bookkeeping.
///
/// Mail.app must be running and the user must have granted automation access.
public final class Sender: @unchecked Sendable {
    public static let shared = Sender()
    private init() {}

    public struct SendRequest {
        public let to: [String]
        public let cc: [String]
        public let bcc: [String]
        public let subject: String
        public let body: String
        public let isHTML: Bool

        public init(to: [String], cc: [String] = [], bcc: [String] = [],
                    subject: String, body: String, isHTML: Bool = false) {
            self.to = to
            self.cc = cc
            self.bcc = bcc
            self.subject = subject
            self.body = body
            self.isHTML = isHTML
        }
    }

    public struct SendResult {
        public let success: Bool
        public let error: String?
    }

    /// Send a message via Mail.app AppleScript bridge.
    ///
    /// Constructs an AppleScript that:
    /// 1. Creates a new outgoing message.
    /// 2. Adds recipients.
    /// 3. Sets subject + body.
    /// 4. Calls `send`.
    ///
    /// Runs synchronously on the calling thread — callers should dispatch to a background queue.
    public func send(_ request: SendRequest) -> SendResult {
        guard !request.to.isEmpty else {
            return SendResult(success: false, error: "No recipients specified")
        }

        let toLines = request.to.map { "make new to recipient at end of to recipients of theMessage with properties {address:\"\($0)\"}" }
        let ccLines = request.cc.map { "make new cc recipient at end of cc recipients of theMessage with properties {address:\"\($0)\"}" }
        let bccLines = request.bcc.map { "make new bcc recipient at end of bcc recipients of theMessage with properties {address:\"\($0)\"}" }

        // Escape backslashes and double-quotes in body/subject
        let safeSubject = request.subject
            .replacingOccurrences(of: "\\", with: "\\\\")
            .replacingOccurrences(of: "\"", with: "\\\"")
        let safeBody = request.body
            .replacingOccurrences(of: "\\", with: "\\\\")
            .replacingOccurrences(of: "\"", with: "\\\"")

        let allRecipientLines = (toLines + ccLines + bccLines).joined(separator: "\n        ")

        let script = """
        tell application "Mail"
            set theMessage to make new outgoing message with properties {subject:"\(safeSubject)", content:"\(safeBody)", visible:false}
            tell theMessage
                \(allRecipientLines)
            end tell
            send theMessage
        end tell
        """

        var errorDict: NSDictionary?
        guard let appleScript = NSAppleScript(source: script) else {
            return SendResult(success: false, error: "Failed to compile AppleScript")
        }

        appleScript.executeAndReturnError(&errorDict)

        if let err = errorDict {
            let msg = err[NSAppleScript.errorMessage] as? String ?? "Unknown AppleScript error"
            NSLog("IMailSender: AppleScript error: \(msg)")
            return SendResult(success: false, error: msg)
        }

        NSLog("IMailSender: sent '\(request.subject)' to \(request.to.joined(separator: ", "))")
        return SendResult(success: true, error: nil)
    }
}
