import Foundation

/// Reads the iOS host-app artifacts (`HostApp.swift`, `Info.plist`,
/// `AppIcon.png`) from a fixed location and emits a Swift source file
/// containing them as base64-encoded constants. Invoked by the
/// `EmbedHostAppSource` build-tool plugin (see
/// `Plugins/EmbedHostAppSource/EmbedHostAppSource.swift`).
///
/// Why base64 over `[UInt8]` arrays: the raw bytes total ~88KB; a
/// `[UInt8]` literal would be ~530KB of Swift source and slow to
/// compile. Base64 keeps the output ~120KB and readable.
///
/// Why not just use raw string literals: the iOS host app source
/// contains `"""` and other delimiters that would require careful
/// escaping. Base64 sidesteps the entire encoding-concerns space.
///
/// Byte-equivalence with the prior hand-written `IOSHostAppSource.swift`
/// blob is the load-bearing acceptance gate for #7
/// (`IOSHostBuilderHashTests.hashIsStable`). Decoding base64 → UTF-8 →
/// `String` is byte-identical with the prior triple-quoted string-
/// literal source IFF the input files contain exactly those bytes.
@main
enum EmbedHostAppSourceTool {
    static func main() throws {
        let args = CommandLine.arguments
        guard args.count == 5 else {
            fail("usage: \(args.first ?? "tool") <hostAppSwift> <infoPlist> <iconPng> <output>")
        }

        let hostAppB64 = readBase64(args[1])
        let infoPlistB64 = readBase64(args[2])
        let iconB64 = readBase64(args[3])
        let outputPath = args[4]

        // Interpolating these directly into a Swift source string is safe
        // because the base64 alphabet (`A-Z a-z 0-9 + /` plus `=` padding) is
        // a strict subset of ASCII printable with no `"`, no `\`, no
        // interpolation triggers. If this tool is ever extended to embed
        // non-base64 payloads, the substitution would need explicit escaping.
        let generated = """
            // GENERATED by EmbedHostAppSourceTool — DO NOT EDIT.
            // Source files live under `HostAppSource/` at the package root.
            // Re-run `swift build` after editing them.
            import Foundation

            enum IOSHostAppSource {
                static let code: String = _decodeUTF8(_hostAppCodeBase64, label: "HostApp.swift")
                static let infoPlist: String = _decodeUTF8(_infoPlistBase64, label: "Info.plist")
            }

            enum IOSAppIconData {
                static let bytes: Data = _decodeData(_iconBase64, label: "AppIcon.png")
            }

            private let _hostAppCodeBase64 = "\(hostAppB64)"
            private let _infoPlistBase64 = "\(infoPlistB64)"
            private let _iconBase64 = "\(iconB64)"

            private func _decodeData(_ b64: String, label: String) -> Data {
                guard let data = Data(base64Encoded: b64) else {
                    preconditionFailure(
                        "EmbedHostAppSourceTool produced invalid base64 for \\(label) — rerun `swift build`."
                    )
                }
                return data
            }

            private func _decodeUTF8(_ b64: String, label: String) -> String {
                String(decoding: _decodeData(b64, label: label), as: UTF8.self)
            }

            """

        do {
            try Data(generated.utf8).write(to: URL(fileURLWithPath: outputPath))
        } catch {
            fail("could not write \(outputPath): \(error.localizedDescription)")
        }
    }

    /// Emit a stderr line and exit non-zero. Build-tool failures should
    /// be diagnosable from CI logs without a Swift backtrace.
    static func fail(_ message: String) -> Never {
        FileHandle.standardError.write(Data("EmbedHostAppSourceTool: \(message)\n".utf8))
        exit(1)
    }

    static func readBase64(_ path: String) -> String {
        do {
            let data = try Data(contentsOf: URL(fileURLWithPath: path))
            return data.base64EncodedString()
        } catch {
            fail("could not read \(path): \(error.localizedDescription)")
        }
    }
}
