//
//  WENotificationInboxImpl.swift
//  WebEngage Inbox Implementation
//

import Foundation
import React
import WebEngage
import WENotificationInbox

@objc public protocol WENotificationInboxDelegate: AnyObject {
  func sendEvent(name: String, result: NSDictionary)
}

@objc(WENotificationInboxImpl)
public class WENotificationInboxImpl: NSObject {
  @objc public weak var delegate: WENotificationInboxDelegate?
  
  private let wegNIVersion = "2.0.0"
  
  @objc public override init() {
    super.init()
    WENotificationInbox.initialize()
  }
  
  @objc public func initWENotificationInbox() {
    let key: WegVersionKey = .RNNI
    WebEngage.sharedInstance().setVersionForChildSDK(wegNIVersion, for: key)
  }
  
  @objc public func onNotificationIconClick() {
    WENotificationInbox.shared.onNotificationIconClick()
  }
  
  @objc public func getNotificationCount(_ callback: @escaping RCTResponseSenderBlock) {
    WENotificationInbox.shared.getUserNotificationCount { [weak self] data, error in
      guard let self = self else { return }
      
      if let number = data as? NSNumber {
        callback(["\(number.intValue)", NSNull()])
      } else if let string = data as? String {
        callback([string, NSNull()])
      } else if let errorMap = error {
        self.handleNotificationCountError(error: errorMap, callback)
      } else {
        callback([NSNull(), ["error": "Unknown error occurred"]])
      }
    }
  }
  
  @objc public func getNotificationList(_ offsetJSON: String?, callback: @escaping RCTResponseSenderBlock) {
    var lastInboxMessage: WEInboxMessage? = nil
    if let offset = offsetJSON, let jsonData = offset.data(using: .utf8) {
      do {
        if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
          lastInboxMessage = WEInboxMessage(param: json)
        }
      } catch {
        print("[WEInboxImpl] Failed to parse offset JSON: \(error.localizedDescription)")
      }
    }
    
    WENotificationInbox.shared.getNotificationList(lastInboxData: lastInboxMessage) { [weak self] response, error in
      guard let self = self else { return }
      if let response = response {
        self.handleNotificationListSuccess(response: response, callback)
      } else if let error = error {
        self.handleNotificationError(error: error, callback)
      } else {
        callback([NSNull(), ["error": "Unknown error occurred"]])
      }
    }
  }
  
  @objc public func markRead(_ readMap: NSDictionary) {
    WENIHelper.shared.handleInboxEvent(event_name: "markRead", map: readMap)
  }
  
  @objc public func markUnread(_ readMap: NSDictionary) {
    WENIHelper.shared.handleInboxEvent(event_name: "markUnread", map: readMap)
  }
  
  @objc public func markDelete(_ readMap: NSDictionary) {
    WENIHelper.shared.handleInboxEvent(event_name: "markDelete", map: readMap)
  }
  
  @objc public func trackClick(_ readMap: NSDictionary) {
    WENIHelper.shared.handleInboxEvent(event_name: "trackClick", map: readMap)
  }
  
  @objc public func trackView(_ readMap: NSDictionary) {
    WENIHelper.shared.handleInboxEvent(event_name: "trackView", map: readMap)
  }
  
  @objc public func readAll(_ notificationList: NSArray) {
    WENIHelper.shared.handleMultipleInboxEvent(event_name: "markRead", notificationList: notificationList)
  }
  
  @objc public func unReadAll(_ notificationList: NSArray) {
    WENIHelper.shared.handleMultipleInboxEvent(event_name: "markUnread", notificationList: notificationList)
  }
  
  @objc public func deleteAll(_ notificationList: NSArray) {
    WENIHelper.shared.handleMultipleInboxEvent(event_name: "markDelete", notificationList: notificationList)
  }
  
  private func handleNotificationListSuccess(response: WEInboxData, _ callback: @escaping RCTResponseSenderBlock) {
    let messageList = response.messageList
    let jsonArray = messageList.map { $0.jsonData }
    let jsonString = convertToJsonString(jsonArray: jsonArray)
    let apiResponse: [String: Any] = [
      "hasNext": response.hasNextPage,
      "messageList": jsonString
    ]
    callback([apiResponse, NSNull()])
  }
  
  private func handleNotificationError(error: WEInboxError, _ callback: @escaping RCTResponseSenderBlock) {
    let errorMap: [String: Any] = [
      "error": [
        "response": [
          "status": error.status,
          "message": error.localizedDescription
        ]
      ]
    ]
    callback([NSNull(), errorMap])
  }
  
  private func handleNotificationCountError(error: WEInboxError, _ callback: @escaping RCTResponseSenderBlock) {
    let errorMap: [String: Any] = [
      "error": [
        "response": [
          "status": error.status,
          "message": error.localizedDescription
        ]
      ]
    ]
    callback([NSNull(), errorMap])
  }
  
  private func convertToJsonString(jsonArray: Any) -> String {
    do {
      let jsonData = try JSONSerialization.data(withJSONObject: jsonArray, options: [])
      if let jsonString = String(data: jsonData, encoding: .utf8) {
        return jsonString
      }
    } catch {
      print("[WEInboxImpl] Failed to convert to JSON string: \(error.localizedDescription)")
    }
    return ""
  }

}

extension WENotificationInboxImpl {
  @objc public static var supportedEvents: [String] {
    return ["notificationList", "notificationCount"]
  }
}
