//
//  RTNBlazeSdkModule+AppEvents.swift
//  blaze-rtn-sdk
//
//  Created by Reuven Levitsky on 20/02/2024.
//

import Foundation
import BlazeSDK

extension RTNBlazeSdkModule {
    
    enum SupportedAppEvents: String, CaseIterable {
        
        // Global delegate.
        case onErrorThrown = "Blaze.onErrorThrown"
        case onEventTriggered = "Blaze.onEventTriggered"
        
        // Entry point delegate.
        case onDataLoadStarted = "Blaze.onDataLoadStarted"
        case onDataLoadComplete = "Blaze.onDataLoadComplete"
        case onPlayerDidAppear = "Blaze.onPlayerDidAppear"
        case onPlayerDidDismiss = "Blaze.onPlayerDidDismiss"
        case onTriggerCTA = "Blaze.onTriggerCTA"
        case onTriggerPlayerBodyTextLink = "Blaze.onTriggerPlayerBodyTextLink"
        case onPlayerEventTriggered = "Blaze.onPlayerEventTriggered"
        
    }
    
    struct Constants {
        static let eventDataKey = "eventData"
        static let playerTypeKey = "playerType"
        static let sourceIdKey = "sourceId"
        static let actionTypeKey = "actionType"
        static let actionParamKey = "actionParam"
        static let itemsCountKey = "itemsCount"
        static let playerEventType = "playerEventType"
        static let playerEventParams = "playerEventParams"
        
    }
    
    func createOnEventTriggeredEvent(_ eventData: BlazeSDK.BlazeAnalytics) -> BlazeAppEvent? {
        guard let eventJson = eventData.asJsonString else {
            return nil
        }
        
        let eventData: [String: AnyHashable] = [
            Constants.eventDataKey: eventJson
        ]
        return .init(name: SupportedAppEvents.onEventTriggered.rawValue,
                     body: eventData)
    }
    
    func createOnErrorThrownEvent(_ error: BlazeSDK.BlazeError) -> BlazeAppEvent {
        let eventData: [String: AnyHashable] = [
            "domain": "\(error.domain)",
            "reason": error.failureReason, // Access the error domain
            "message": error.errorMessage  // Access the error message
        ]
        
        return .init(name: SupportedAppEvents.onErrorThrown.rawValue,
                     body: eventData)
    }
    
    func createOnDataLoadStartedEvent(playerType: BlazePlayerType,
                                      sourceId: String?) -> BlazeAppEvent {
        let eventData: [String: AnyHashable] = [
            Constants.playerTypeKey: playerType.toReactValue,
            Constants.sourceIdKey: sourceId
        ]
        
        return .init(name: SupportedAppEvents.onDataLoadStarted.rawValue,
                     body: eventData)
    }
    
    func createOnDataLoadCompleteEvent(playerType: BlazePlayerType,
                                       sourceId: String?,
                                       itemsCount: Int,
                                       result: BlazeResult) -> BlazeAppEvent {
        var eventData: [String: AnyHashable] = [
            Constants.playerTypeKey: playerType.toReactValue,
            Constants.sourceIdKey: sourceId,
            Constants.itemsCountKey: itemsCount
        ]
        
        if case .failure(let error) = result {
            eventData["error"] = error.errorMessage
        }
        
        return .init(name: SupportedAppEvents.onDataLoadComplete.rawValue,
                     body: eventData)
    }
    
    func createOnPlayerDidAppearEvent(playerType: BlazePlayerType,
                                      sourceId: String?) -> BlazeAppEvent {
        let eventData: [String: AnyHashable] = [
            Constants.playerTypeKey: playerType.toReactValue,
            Constants.sourceIdKey: sourceId
        ]
        
        return .init(name: SupportedAppEvents.onPlayerDidAppear.rawValue,
                     body: eventData)
    }
    
    func createOnPlayerDidDismissEvent(playerType: BlazePlayerType,
                                       sourceId: String?) -> BlazeAppEvent {
        let eventData: [String: AnyHashable] = [
            Constants.playerTypeKey: playerType.toReactValue,
            Constants.sourceIdKey: sourceId
        ]
        
        return .init(name: SupportedAppEvents.onPlayerDidDismiss.rawValue,
                     body: eventData)
    }
    
    func createOnTriggerCTAEvent(playerType: BlazePlayerType,
                                 sourceId: String?,
                                 actionType: BlazeCTAActionType,
                                 actionParam: String) -> BlazeAppEvent {
        let eventData: [String: AnyHashable] = [
            Constants.playerTypeKey: playerType.toReactValue,
            Constants.sourceIdKey: sourceId,
            Constants.actionTypeKey: actionType.toReactValue,
            Constants.actionParamKey: actionParam
        ]
        
        return .init(name: SupportedAppEvents.onTriggerCTA.rawValue,
                     body: eventData)
    }
    
    func createOnTriggerPlayerBodyTextLinkEvent(playerType: BlazePlayerType,
                                                sourceId: String?,
                                                actionParam: String) -> BlazeAppEvent {
        let eventData: [String: AnyHashable] = [
            Constants.playerTypeKey: playerType.toReactValue,
            Constants.sourceIdKey: sourceId,
            Constants.actionParamKey: actionParam
        ]
        
        return .init(name: SupportedAppEvents.onTriggerPlayerBodyTextLink.rawValue,
                     body: eventData)
    }
    
    func createOnPlayerEventTriggeredEvent(playerType: BlazePlayerType,
                                           sourceId: String?,
                                           event: BlazePlayerEvent) -> BlazeAppEvent? {
        guard let eventType = event.toReactEventType,
              let eventParams = event.toReactEventParams else {
            return nil
        }
                
        let eventData: [String: AnyHashable] = [
            Constants.playerTypeKey: playerType.toReactValue,
            Constants.sourceIdKey: sourceId,
            Constants.playerEventType: eventType,
            Constants.playerEventParams: eventParams
        ]
        
        return .init(name: SupportedAppEvents.onPlayerEventTriggered.rawValue,
                     body: eventData)
    }
    
}

extension BlazePlayerType {
    
    var toReactValue: String? {
        switch self {
        case .moments:
            return "Moments"
        case .stories:
            return "Stories"
        case .videos:
            return "Videos"
        }
    }
    
}

extension BlazeCTAActionType {
    
    var toReactValue: String? {
        switch self {
        case .deeplink:
            return "Deeplink"
        case .web:
            return "Web"
        }
    }
    
}
