import Foundation
import Capacitor
import NativeLib

@objc(TasFirebaseCrashlyticsPlugin)
public class TasFirebaseCrashlyticsPlugin: CAPPlugin {
    public let errorMessageMissing = "message must be provided.";
    public let errorKeyMissing = "key must be provided.";
    public let errorValueMissing = "value must be provided.";
    public let errorUserIdMissing = "userId must be provided.";
    public let errorEnabledMissing = "enabled must be provided.";
    
    public override func load() {
        CrashlyticsService.shared
    }

    @objc func crash(_ call: CAPPluginCall) {
        call.resolve()
        CrashlyticsService.shared.crash()
    }

    @objc func addLogMessage(_ call: CAPPluginCall) {
        guard let message = call.getString("message") else {
            call.reject(errorMessageMissing)
            return;
        }
        CrashlyticsService.shared.addLogMessage(message)
        call.resolve()
    }

    @objc func setEnabled(_ call: CAPPluginCall) {
        guard let enabled = call.getBool("enabled") else {
            call.reject(errorEnabledMissing)
            return;
        }
        CrashlyticsService.shared.setEnabled(enabled)
        call.resolve()
    }

    @objc func recordException(_ call: CAPPluginCall) {
        guard let message = call.getString("message") else {
            call.reject(errorMessageMissing)
            return;
        }

        let stacktrace = call.getArray("stacktrace", JSObject.self)
        if (stacktrace == nil || stacktrace!.isEmpty) {
            let domain = call.getString("domain") ?? ""
            let code = call.getInt("code") ?? -1001
            CrashlyticsService.shared.recordException(message, domain, code)
        } else {
            CrashlyticsService.shared.recordExceptionWithStacktrace(message, parseStackTrace(stacktrace!))
        }
        call.resolve()
    }
    
    private func parseStackTrace(_ stacktrace: [JSObject]) -> [(String, String, Int)] {
        var customFrames: [(String, String, Int)] = []
        for stackFrame in stacktrace {
            let functionName = (stackFrame["functionName"] as? String) ?? "(anonymous function)"
            let fileName = (stackFrame["fileName"] as? String) ?? "(unknown file)"
            let line = (stackFrame["lineNumber"] as? Int) ?? -1

            let info = (functionName, fileName, line)
            customFrames.append(info)
        }
        return customFrames
    }
}
