import Foundation
import AVFoundation
import Async
import UIKit
import WowonderMessengerSDK
import OneSignalFramework
import CommonCrypto

class AppInstance {
    
    // MARK: - Properties
    
    static let instance = AppInstance()
    
    var userId: String? = nil
    var sessionId: String? = nil
    var genderText: String? = "all"
    var profilePicText: String? = "all"
    var statusText: String? = "all"
    var addCount: Int? = 0
    var connectivity_setting = "0"
    var userProfile: UserData?
    var userSetting: [String : Any]?
    var siteSetting: SettingsConfig?
    var _userId: String {
        get {
            return self.userId ?? ""
        }
    }
    var _sessionId: String {
        get {
            return self.sessionId ?? ""
        }
    }
    var isDownloadImage = false
    var isDownloadVideo = false
    
    func getDownloadMediaData() {
        if appDelegate.reachability.connection == .cellular {
            self.isDownloadImage = UserDefaults.standard.getDownloadOption(Key: "Mobile_Data_Download").contains("Image")
        } else if appDelegate.reachability.connection == .wifi {
            self.isDownloadImage = UserDefaults.standard.getDownloadOption(Key: "WiFi_Data_Download").contains("Image")
        } else {
            self.isDownloadImage = false
        }
        if appDelegate.reachability.connection == .cellular {
            self.isDownloadVideo = UserDefaults.standard.getDownloadOption(Key: "Mobile_Data_Download").contains("Video")
        } else if appDelegate.reachability.connection == .wifi {
            self.isDownloadVideo = UserDefaults.standard.getDownloadOption(Key: "WiFi_Data_Download").contains("Video")
        } else {
            self.isDownloadVideo = false
        }
    }
    
    func generateThumbnail(from videoURL: URL?, completion: @escaping (UIImage?) -> Void) {
        guard let videoURL = videoURL else {
            print("The video URL is not valid")
            completion(nil)
            return
        }
        let asset = AVAsset(url: videoURL)
        let assetImageGenerator = AVAssetImageGenerator(asset: asset)
        assetImageGenerator.appliesPreferredTrackTransform = true
        let time = CMTime(seconds: 1, preferredTimescale: 1) // Get thumbnail at 1 second into the video
        do {
            let thumbnailCGImage = try assetImageGenerator.copyCGImage(at: time, actualTime: nil)
            let thumbnailImage = UIImage(cgImage: thumbnailCGImage)
            completion(thumbnailImage)
        } catch {
            print("Error generating thumbnail: \(error)")
            completion(nil)
        }
    }
    
    func getUserSession() -> Bool {
        let localUserSessionData = UserDefaults.standard.getUserSessions(Key: Local.USER_SESSION.User_Session)
        if localUserSessionData.isEmpty {
            return false
        } else {
            self.userId = localUserSessionData[Local.USER_SESSION.User_id] as? String
            self.sessionId = localUserSessionData[Local.USER_SESSION.Access_token] as? String
            return true
        }
    }
    
    func fetchUserProfile(completion: ((_ success: UserDataModel?) -> ())? = nil) {
        let status = AppInstance.instance.getUserSession()
        if status {
            let userId = AppInstance.instance.userId
            let sessionId = AppInstance.instance.sessionId
            Async.background {
                GetUserDataManager.instance.getUserData(user_id: userId ?? "", session_Token: sessionId ?? "", fetch_type: API.Params.user_data) { (success, sessionError, serverError, error) in
                    Async.main {
                        if success != nil {
                            AppInstance.instance.userProfile = success?.user_data ?? nil
                            if (OneSignal.User.externalId != AppInstance.instance.userProfile?.user_id ?? "") {
                                OneSignal.logout()
                                OneSignal.login(AppInstance.instance.userProfile?.user_id ?? "")
                            }
                            /*self.socketHelper.emit_join(username: AppInstance.instance.userProfile?.username ?? "", user_id: AppInstance.instance._userId)*/
                            if let completion = completion {
                                completion(success)
                            }
                        } else if sessionError != nil {
                            print("sessionError = \(sessionError?.errors?.error_text ?? "")")
                        } else if serverError != nil {
                            print("serverError = \(serverError?.errors?.error_text ?? "")")
                        } else {
                            print("error = \(error?.localizedDescription ?? "")")
                        }
                    }
                }
            }
        } else {
            print(InterNetError)
        }
    }
    
    func decryptAESInECBModeToString(text: String, key: String) -> String? {
        guard let data = Data(base64Encoded: text.replacingOccurrences(of: "$Ap1_", with: ""), options: .ignoreUnknownCharacters) else { return nil }
        guard let keyData = key.data(using: String.Encoding.utf8) else { return nil }
        guard let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) else { return nil }
        let keyLength = size_t(kCCKeySizeAES128)
        let operation: CCOperation = UInt32(kCCDecrypt)
        let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES)
        let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
        let iv: String = ""
        var numBytesEncrypted: size_t = 0
        let cryptStatus = CCCrypt(operation, algoritm, options, (keyData as NSData).bytes, keyLength, iv, (data as NSData).bytes, data.count, cryptData.mutableBytes, cryptData.length, &numBytesEncrypted)
        if cryptStatus < 0 {
            return nil
        } else {
            if UInt32(cryptStatus) == UInt32(kCCSuccess) {
                cryptData.length = Int(numBytesEncrypted)
                var str = String(decoding : cryptData as Data, as: UTF8.self)
                if str.isEmpty {
                    return text
                } else {
                    str = str.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
                    return str
                }
            } else {
                return text
            }
        }
    }
    
}
