import Foundation

public enum OpenClawKitResources {
    /// Resource bundle for OpenClawKit.
    ///
    /// Locates the SwiftPM-generated resource bundle, checking multiple locations:
    /// 1. Inside Bundle.main (packaged apps)
    /// 2. Bundle.module (SwiftPM development/tests)
    /// 3. Falls back to Bundle.main if not found (resource lookups will return nil)
    ///
    /// This avoids a fatal crash when Bundle.module can't locate its resources
    /// in packaged .app bundles where the resource bundle path differs from
    /// SwiftPM's expectations.
    public static let bundle: Bundle = locateBundle()

    private static let bundleName = "OpenClawKit_OpenClawKit"

    private static func locateBundle() -> Bundle {
        // 1. Check inside Bundle.main (packaged apps copy resources here)
        if let mainResourceURL = Bundle.main.resourceURL {
            let bundleURL = mainResourceURL.appendingPathComponent("\(bundleName).bundle")
            if let bundle = Bundle(url: bundleURL) {
                return bundle
            }
        }

        // 2. Check Bundle.main directly for embedded resources
        if Bundle.main.url(forResource: "tool-display", withExtension: "json") != nil {
            return Bundle.main
        }

        // 3. Try Bundle.module (works in SwiftPM development/tests)
        // Wrap in a function to defer the fatalError until actually called
        if let moduleBundle = loadModuleBundleSafely() {
            return moduleBundle
        }

        // 4. Fallback: return Bundle.main (resource lookups will return nil gracefully)
        return Bundle.main
    }

    private static func loadModuleBundleSafely() -> Bundle? {
        // Bundle.module is generated by SwiftPM and will fatalError if not found.
        // We check likely locations manually to avoid the crash.
        let candidates: [URL?] = [
            Bundle.main.resourceURL,
            Bundle.main.bundleURL,
            Bundle(for: BundleLocator.self).resourceURL,
            Bundle(for: BundleLocator.self).bundleURL,
        ]

        for candidate in candidates {
            guard let baseURL = candidate else { continue }

            // SwiftPM often places the resource bundle next to (or near) the test runner bundle,
            // not inside it. Walk up a few levels and check common container paths.
            var roots: [URL] = []
            roots.append(baseURL)
            roots.append(baseURL.appendingPathComponent("Resources"))
            roots.append(baseURL.appendingPathComponent("Contents/Resources"))

            var current = baseURL
            for _ in 0 ..< 5 {
                current = current.deletingLastPathComponent()
                roots.append(current)
                roots.append(current.appendingPathComponent("Resources"))
                roots.append(current.appendingPathComponent("Contents/Resources"))
            }

            for root in roots {
                let bundleURL = root.appendingPathComponent("\(bundleName).bundle")
                if let bundle = Bundle(url: bundleURL) {
                    return bundle
                }
            }
        }

        return nil
    }
}

// Helper class for bundle lookup via Bundle(for:)
private final class BundleLocator {}
