import Foundation
import QualtricsDXA
import React

// Swift implementation of the DXA React Native bridge
@objc(DxaReactNativeImpl)
class DxaReactNativeImpl: NSObject {

    // MARK: - Synchronous Methods

    @objc
    func setLoggingTags(_ tags: [String]) -> [String] {
        let logTagDictionary = Dictionary(uniqueKeysWithValues: LogTag.allCases.map { ($0.key(), $0) })

        var allowedTags: Set<LogTag> = []
        for tag in tags {
            guard let tag = logTagDictionary[tag] else {
                print("Error: invalid tag '\(tag)'")
                continue
            }
            allowedTags.insert(tag)
        }
        QualtricsSR.shared.allowedLoggingTags = allowedTags

        return Array(allowedTags.map { $0.key() })
    }

    @objc
    @MainActor
    func initializeProject(_ brandId: String, projectId: String, sdkVersion: String, reactNativeVersion: String) -> NSDictionary {
        UserDefaults.standard.set("DXAMobileIOSReactNative", forKey: "QualtricsClientType")
        UserDefaults.standard.set(sdkVersion, forKey: "QualtricsClientRNSdkVersion")
        UserDefaults.standard.set(reactNativeVersion, forKey: "QualtricsClientRNVersion")

        let result = QualtricsSR.shared.initializeProject(
            brandId: brandId,
            projectId: projectId
        )
        return ["result": String(describing: result)]
    }

    @objc
    func logError(_ message: String? = nil) -> NSDictionary {
        QualtricsSR.shared.logError(message: message)
        return ["result": "success"]
    }

    @objc
    func reportScreenChangeOnNative(
      _ screenChangePayload: NSDictionary
    ) {
        guard let result = parseScreenChangePayload(from: screenChangePayload) else {
            return
        }

        let (screenHierarchy, changeType, detectionType) = result
        QualtricsSR.shared.reportScreenChange(
            screenHierarchy: screenHierarchy,
            changeType: changeType,
            detectionType: detectionType
        )
    }

    // MARK: - Asynchronous Methods

    @objc
    func startRecording(
        _ config: NSDictionary,
        _ resolve: @escaping RCTPromiseResolveBlock,
        _ reject: @escaping RCTPromiseRejectBlock
    ) {
        let customViewTypesToMask = (config["customViewTypesToMask"] as? [String]) ?? []
        var reactNativeViewTypesToMask = [
            String(reflecting: RCTTextView.self),
            String(reflecting: RCTImageView.self),
        ]
        #if RCT_NEW_ARCH_ENABLED
          reactNativeViewTypesToMask.append("RCTParagraphTextView")
        #endif
      
        let additionalViewTypesToMask = reactNativeViewTypesToMask + customViewTypesToMask

        var dxaConfiguration: DxaConfiguration? = nil

        do {
            dxaConfiguration = try DxaConfiguration(
                additionalViewTypesToMask: additionalViewTypesToMask,
                automaticNavigationTracking: false
            )
        } catch (let error) {
            reject("ERROR", "Failed to initialize DxaConfiguration", error)
            return
        }

        guard let dxaConfig = dxaConfiguration else {
            reject("ERROR:", "Failed to initialize DxaConfiguration", nil)
            return
        }

        Task {
            let result = await QualtricsSR.shared.startRecording(
                dxaConfiguration: dxaConfig
            )

            guard case .success(let message, let sessionInfo) = result else {
                if case .fail(let error) = result {
                    resolve(["result": "fail", "error": error ?? "Unknown error"])
                } else {
                    resolve(["result": String(describing: result)])
                }
                return
            }

            resolve([
                "result": "success",
                "message": message,
                "sessionId": sessionInfo.sessionId,
                "sessionStartTimeMillis": sessionInfo.sessionStartTimeMillis
            ])
        }
    }

    @objc
    func stopRecording(
        _ resolve: @escaping RCTPromiseResolveBlock,
        _ reject: @escaping RCTPromiseRejectBlock
    ) {
        Task {
            let result = await QualtricsSR.shared.stopRecording()
            resolve(["result": String(describing: result)])
        }
    }

    @objc
    func resumeRecording(
      _ resolve: @escaping RCTPromiseResolveBlock,
      _ reject: @escaping RCTPromiseRejectBlock
    ) {
        Task {
            let result = QualtricsSR.shared.resumeRecording()
            resolve(["result": String(describing: result)])
        }
    }

    @objc
    func pauseRecording(
      _ resolve: @escaping RCTPromiseResolveBlock,
      _ reject: @escaping RCTPromiseRejectBlock
    ) {
        Task {
            let result = QualtricsSR.shared.pauseRecording()
            resolve(["result": String(describing: result)])
        }
    }

    // TODO: DXM-1811 Add addLogListener()
}
