#if canImport(PackagePlugin)
import PackagePlugin
import Foundation

/// Build plugin for runtime code generation with BridgeJS.
/// This plugin automatically generates bridge code between Swift and JavaScript
/// during each build process.
@main
struct BridgeJSBuildPlugin: BuildToolPlugin {
    func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] {
        guard let swiftSourceModuleTarget = target as? SwiftSourceModuleTarget else {
            return []
        }
        return [try createGenerateCommand(context: context, target: swiftSourceModuleTarget)]
    }

    private func pathToConfigFile(target: SwiftSourceModuleTarget) -> URL {
        return target.directoryURL.appending(path: "bridge-js.config.json")
    }

    private func createGenerateCommand(context: PluginContext, target: SwiftSourceModuleTarget) throws -> Command {
        let outputSwiftPath = context.pluginWorkDirectoryURL.appending(path: "BridgeJS.swift")

        let inputSwiftFiles = target.sourceFiles.filter {
            !$0.url.path.hasPrefix(context.pluginWorkDirectoryURL.path + "/")
        }
        .map(\.url)

        let configFile = pathToConfigFile(target: target)
        var inputFiles: [URL] = inputSwiftFiles
        if FileManager.default.fileExists(atPath: configFile.path) {
            inputFiles.append(configFile)
        }

        // Include Swift files generated by other plugins applied to this
        // target (available in tools-version 6.0+). This lets BridgeJS
        // process @JS annotations in files produced by earlier plugins
        // without requiring any extra configuration.
        let pluginGeneratedSwiftFiles = target.pluginGeneratedSources.filter {
            $0.pathExtension == "swift"
        }
        inputFiles.append(contentsOf: pluginGeneratedSwiftFiles)

        let inputTSFile = target.directoryURL.appending(path: "bridge-js.d.ts")
        let tsconfigPath = context.package.directoryURL.appending(path: "tsconfig.json")

        var arguments: [String] = [
            "generate",
            "--module-name",
            target.name,
            "--target-dir",
            target.directoryURL.path,
            "--output-dir",
            context.pluginWorkDirectoryURL.path,
            "--always-write", "true",
        ]

        if FileManager.default.fileExists(atPath: inputTSFile.path) {
            inputFiles.append(contentsOf: [inputTSFile, tsconfigPath])
            arguments.append(contentsOf: [
                "--project",
                tsconfigPath.path,
            ])
        }

        let allSwiftFiles = inputSwiftFiles + pluginGeneratedSwiftFiles
        arguments.append(contentsOf: allSwiftFiles.map(\.path))

        return .buildCommand(
            displayName: "Generate BridgeJS code",
            executable: try context.tool(named: "BridgeJSTool").url,
            arguments: arguments,
            inputFiles: inputFiles,
            outputFiles: [outputSwiftPath]
        )
    }
}
#endif
