//
//  ChatUserListBottomVC.swift
//  WoWonder
//
//  Created by UnikApp on 09/12/22.
//  Copyright © 2022 ScriptSun. All rights reserved.
//

import UIKit
import Async
import DropDown
import AVFoundation
import AVKit
import GoogleMaps
import WowonderMessengerSDK
import MobileCoreServices
import FileProvider
import Toast_Swift
import CoreData
import IQKeyboardManagerSwift

protocol ChatUserOptionDelegate {
    func handleChatUserOptionListTap(index: Int, optionName: String, indexPath: IndexPath)
}

class ChatUserListBottomVC: BaseVC {
    
    // MARK: - IBOutlets
    
    @IBOutlet weak var archiveIcon: UIImageView!
    @IBOutlet weak var archiveLabel: UILabel!
    @IBOutlet weak var archiveView: UIControl!
    @IBOutlet weak var deleteIcon: UIImageView!
    @IBOutlet weak var deleteView: UIControl!
    @IBOutlet weak var pinIcon: UIImageView!
    @IBOutlet weak var pinLabel: UILabel!
    @IBOutlet weak var pinView: UIControl!
    @IBOutlet weak var muteNotificationIcon: UIImageView!
    @IBOutlet weak var muteNotificationLabel: UILabel!
    @IBOutlet weak var muteNotificationView: UIControl!
    @IBOutlet weak var markAsReadIcon: UIImageView!
    @IBOutlet weak var markAsReadView: UIControl!
    @IBOutlet weak var blockIcon: UIImageView!
    @IBOutlet weak var blockLabel: UILabel!
    @IBOutlet weak var blockView: UIControl!
    @IBOutlet weak var viewProfileIcon: UIImageView!
    @IBOutlet weak var viewProfileView: UIControl!
    @IBOutlet weak var reportThisUserIcon: UIImageView!
    @IBOutlet weak var reportThisUserLabel: UILabel!
    @IBOutlet weak var reportThisUserView: UIControl!
    
    // MARK: - Properties
    
    var sheetHeight: CGFloat = 0
    var sheetBackgroundColor: UIColor = .color_fill
    var sheetCornerRadius: CGFloat = 20
    private var hasSetOriginPoint = false
    private var originPoint: CGPoint?
    var delegate: ChatUserOptionDelegate?
    var indexPath = IndexPath()
    var user: Users?
    
    // MARK: - View Life Cycles
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        
        self.initialConfig()
    }
    
    override func viewDidLayoutSubviews() {
        if !hasSetOriginPoint {
            hasSetOriginPoint = true
            originPoint = view.frame.origin
        }
    }
    
    // MARK: - Selectors
    
    // Archive Button Action
    @IBAction func archiveButtonAction(_ sender: UIControl) {
        self.dismiss(animated: true) {
            self.delegate?.handleChatUserOptionListTap(index: 0, optionName: "Archive", indexPath: self.indexPath)
        }
    }
    
    // Delete Button Action
    @IBAction func deleteButtonAction(_ sender: UIControl) {
        self.dismiss(animated: true) {
            self.delegate?.handleChatUserOptionListTap(index: 1, optionName: "Delete", indexPath: self.indexPath)
        }
    }
    
    // Pin Button Action
    @IBAction func pinButtonAction(_ sender: UIControl) {
        self.dismiss(animated: true) {
            self.delegate?.handleChatUserOptionListTap(index: 2, optionName: "Pin", indexPath: self.indexPath)
        }
    }
    
    // Mute Notification Button Action
    @IBAction func muteNotificationButtonAction(_ sender: UIControl) {
        self.dismiss(animated: true) {
            self.delegate?.handleChatUserOptionListTap(index: 3, optionName: "Mute Notification", indexPath: self.indexPath)
        }
    }
    
    // Mark As Read Button Action
    @IBAction func markAsReadButtonAction(_ sender: UIControl) {
        self.dismiss(animated: true) {
            self.delegate?.handleChatUserOptionListTap(index: 4, optionName: "Mark as read", indexPath: self.indexPath)
        }
    }
    
    // Block Button Action
    @IBAction func blockButtonAction(_ sender: UIControl) {
        self.dismiss(animated: true) {
            self.delegate?.handleChatUserOptionListTap(index: 5, optionName: "Block", indexPath: self.indexPath)
        }
    }
    
    // View Profile Button Action
    @IBAction func viewProfileButtonAction(_ sender: UIControl) {
        self.dismiss(animated: true) {
            self.delegate?.handleChatUserOptionListTap(index: 6, optionName: "View Profile", indexPath: self.indexPath)
        }
    }
    
    // Report This User Button Action
    @IBAction func reportThisUserButtonAction(_ sender: UIControl) {
        self.dismiss(animated: true) {
            self.delegate?.handleChatUserOptionListTap(index: 7, optionName: "Report this user", indexPath: self.indexPath)
        }
    }
    
    // MARK: - Helper Functions
    
    // Initial Config
    func initialConfig() {
        self.sheetHeight = 336 + 32 + self.view.safeAreaBottom
        view.frame.size.height = sheetHeight
        view.isUserInteractionEnabled = true
        view.backgroundColor = sheetBackgroundColor
        view.roundCorners(corners: [.topLeft, .topRight], radius: sheetCornerRadius)
        self.setPanGesture()
        self.setUpUI()
    }
    
    // SetUp UI
    func setUpUI() {
        self.archiveLabel.text = self.user?.user_mute?.archive == "yes" ? "Unarchive" : "Archive"
        self.pinLabel.text = self.user?.user_mute?.pin == "yes" ? "UnPin" : "Pin"
        self.muteNotificationLabel.text = self.user?.user_mute?.notify == "no" ? "Unmute notification" : "Mute notification"
        self.blockLabel.text = (self.user?.is_blocked ?? false) ? "Unblock" : "Block"
        self.reportThisUserLabel.text = (self.user?.is_reported ?? false) ? "Cancel reporting" : "Report this user"
    }
    
    // Set Pan Gesture
    func setPanGesture() {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureRecognizerAction))
        view.addGestureRecognizer(panGesture)
    }
    
    // Gesture Recognizer
    @objc func panGestureRecognizerAction(sender: UIPanGestureRecognizer) {
        let translation = sender.translation(in: view)
        // Not allowing the user to drag the view upward
        guard translation.y >= 0 else { return }
        view.frame.origin = CGPoint(
            x: 0,
            y: self.originPoint!.y + translation.y
        )
        if sender.state == .ended {
            self.dismiss(animated: true, completion: nil)
        }
    }
    
}

// MARK: ChatUserOptionDelegate Methods
extension ChatUserListVC: ChatUserOptionDelegate {
    
    func handleChatUserOptionListTap(index: Int, optionName: String, indexPath: IndexPath) {
        var user: Users?
        switch self.listType {
        case .CHATS:
            user = self.saveDataArray[indexPath.row].getFirstChatUser()?.user
        case .GROUP:
            user = nil
        case .ARCHIVE:
            user = self.archiveChats[indexPath.row].getFirstChatUser()?.user
        }
        guard let user = user else { return }
        switch index {
        case 0:
            if user.user_mute?.archive == "yes" {
                self.archiveChat(archive: "no", chat_id: user.chat_id ?? "")
            } else {
                self.archiveChat(archive: "yes", chat_id: user.chat_id ?? "")
            }
        case 1:
            self.deleteChat(user_id: user.user_id ?? "", indexPath: indexPath)
        case 2:
            if user.user_mute?.pin == "yes" {
                self.pinChat(pin: "no", chat_id: user.chat_id ?? "")
            } else {
                self.pinChat(pin: "yes", chat_id: user.chat_id ?? "")
            }
        case 3:
            if user.user_mute?.notify == "yes" {
                self.notifyChat(notify: "no", chat_id: user.chat_id ?? "")
            } else {
                self.notifyChat(notify: "yes", chat_id: user.chat_id ?? "")
            }
        case 4:
            print("")
        case 5:
            if user.is_blocked {
                self.blockUser(user_id: user.user_id ?? "", block_action: "un-block")
            } else {
                if let alertVC = R.storyboard.popup.warningAlertVC() {
                    alertVC.delegate = self
                    alertVC.titleText  = "Delete The Entire Conversation?"
                    alertVC.messageText = "Once you delete your copy of conversation, it cannot be undone."
                    alertVC.okText = "YES"
                    alertVC.cancelText = "NO"
                    self.present(alertVC, animated: true, completion: nil)
                    alertVC.okButton.tag = indexPath.row
                }
                self.blockUser(user_id: user.user_id ?? "", block_action: "block")
            }
        case 6:
            if let newVC = R.storyboard.dashboard.userProfileViewController() {
                newVC.user_id = user.user_id ?? ""
                newVC.users = user
                self.navigationController?.pushViewController(newVC, animated: true)
            }
        case 7:
            if user.is_reported {
                self.reportUser(user: user.user_id ?? "", text: "")
            } else {
                if let newVC = R.storyboard.popup.reportUserAlertVC() {
                    newVC.delegate = self
                    self.present(newVC, animated: true)
                    newVC.updateButton.tag = indexPath.row
                }
            }
        default:
            break
        }
    }
    
    func archiveChat(archive: String, chat_id: String) {
        Async.background {
            GetUserListManager.instance.archiveChat(archive: archive, chat_id: chat_id) { (success, sessionError, serverError, error) in
                if success != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            print(success?.message ?? "")
                            switch self.listType {
                            case .CHATS:
                                self.fetchChatsData()
                            case .GROUP:
                                print("")
                            case .ARCHIVE:
                                self.getArchivedChats()
                            }
                        }
                    }
                } else if sessionError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(sessionError?.errors?.error_text)
                        }
                    }
                } else if serverError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(serverError?.errors?.error_text)
                        }
                    }
                } else {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(error?.localizedDescription)
                        }
                    }
                }
            }
        }
    }
    
    func deleteChat(user_id: String, indexPath: IndexPath) {
        Async.background {
            GetUserListManager.instance.deleteChat(user_id: user_id) { (success, sessionError, serverError, error) in
                if success != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            print(success?.message ?? "")
                            self.view.makeToast(success?.message)
                            let appDelegate = (UIApplication.shared.delegate) as? AppDelegate
                            let context = appDelegate?.persistentContainer.viewContext
                            let predicate = NSPredicate(format: "%K == %@", #keyPath(Messages.chat_id), self.saveDataArray[indexPath.row].chat_id ?? "")
                            let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Messages")
                            fetchRequest.predicate = predicate
                            let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
                            do {
                                try context?.execute(deleteRequest)
                                try context?.save()
                            } catch {
                                print("error >>>>> ", error.localizedDescription)
                            }
                            let userPredicate = NSPredicate(format: "%K == %@", #keyPath(Chats.chat_id), (self.saveDataArray[indexPath.row].chat_id ?? ""))
                            let userFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Chats")
                            userFetchRequest.predicate = userPredicate
                            let userDeleteRequest = NSBatchDeleteRequest(fetchRequest: userFetchRequest)
                            do {
                                try context?.execute(userDeleteRequest)
                                try context?.save()
                            } catch {
                                print("error >>>>> ", error.localizedDescription)
                            }
                            self.saveDataArray.remove(at: indexPath.row)
                            switch self.listType {
                            case .CHATS:
                                self.fetchChatsData()
                            case .GROUP:
                                print("")
                            case .ARCHIVE:
                                self.getArchivedChats()
                            }
                        }
                    }
                } else if sessionError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(sessionError?.errors?.error_text)
                        }
                    }
                } else if serverError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(serverError?.errors?.error_text)
                        }
                    }
                } else {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(error?.localizedDescription)
                        }
                    }
                }
            }
        }
    }
    
    func pinChat(pin: String, chat_id: String) {
        Async.background {
            GetUserListManager.instance.pinChat(pin: pin, chat_id: chat_id) { (success, sessionError, serverError, error) in
                if success != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            print(success?.message ?? "")
                            switch self.listType {
                            case .CHATS:
                                self.fetchChatsData()
                            case .GROUP:
                                print("")
                            case .ARCHIVE:
                                self.getArchivedChats()
                            }
                        }
                    }
                } else if sessionError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(sessionError?.errors?.error_text)
                        }
                    }
                } else if serverError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(serverError?.errors?.error_text)
                        }
                    }
                } else {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(error?.localizedDescription)
                        }
                    }
                }
            }
        }
    }
    
    func notifyChat(notify: String, chat_id: String) {
        Async.background {
            GetUserListManager.instance.notifyChat(notify: notify, chat_id: chat_id) { (success, sessionError, serverError, error) in
                if success != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            print(success?.message ?? "")
                            switch self.listType {
                            case .CHATS:
                                self.fetchChatsData()
                            case .GROUP:
                                print("")
                            case .ARCHIVE:
                                self.getArchivedChats()
                            }
                        }
                    }
                } else if sessionError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(sessionError?.errors?.error_text)
                        }
                    }
                } else if serverError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(serverError?.errors?.error_text)
                        }
                    }
                } else {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(error?.localizedDescription)
                        }
                    }
                }
            }
        }
    }
    
    func blockUser(user_id: String, block_action: String) {
        Async.background {
            BlockUsersManager.instance.blockUser(user_id: user_id, block_action: block_action, completionBlock: { (success, sessionError, serverError, error) in
                if success != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            if success?.blockStatus == "blocked" {
                                self.view.makeToast("User has been blocked!!")
                            } else if success?.blockStatus == "un-blocked" {
                                self.view.makeToast(NSLocalizedString("User has been unblocked!!", comment: "User has been unblocked!!"))
                            } else {
                                self.view.makeToast(success?.blockStatus ?? "")
                            }
                            switch self.listType {
                            case .CHATS:
                                self.fetchChatsData()
                            case .GROUP:
                                print("")
                            case .ARCHIVE:
                                self.getArchivedChats()
                            }
                        }
                    }
                } else if sessionError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(sessionError?.errors?.error_text)
                        }
                    }
                } else if serverError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(serverError?.errors?.error_text)
                        }
                    }
                } else {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(error?.localizedDescription)
                        }
                    }
                }
            })
        }
    }
    
    func reportUser(user: String, text: String) {
        Async.background {
            GetUserListManager.instance.reportUser(user: user, text: text) { (success, sessionError, serverError, error) in
                if success != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            print(success?.code ?? 0)
                            switch self.listType {
                            case .CHATS:
                                self.fetchChatsData()
                            case .GROUP:
                                print("")
                            case .ARCHIVE:
                                self.getArchivedChats()
                            }
                        }
                    }
                } else if sessionError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(sessionError?.errors?.error_text)
                        }
                    }
                } else if serverError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(serverError?.errors?.error_text)
                        }
                    }
                } else {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(error?.localizedDescription)
                        }
                    }
                }
            }
        }
    }
    
}

// MARK: UIViewControllerTransitioningDelegate Methods
extension ChatUserListVC: UIViewControllerTransitioningDelegate {
    
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        BottomSheetPresentationController(presentedViewController: presented, presenting: presenting)
    }
    
}

// MARK: WarningAlertVCDelegate Methods
extension ChatUserListVC: WarningAlertVCDelegate {
    
    func chatAlertOKButtonPressed(_ sender: UIButton) {
        var user: Users?
        switch self.listType {
        case .CHATS:
            user = self.saveDataArray[sender.tag].getFirstChatUser()?.user
        case .GROUP:
            user = nil
        case .ARCHIVE:
            user = self.archiveChats[sender.tag].getFirstChatUser()?.user
        }
        guard let user = user else { return }
        self.deleteChat(user_id: user.user_id ?? "", indexPath: IndexPath(row: sender.tag, section: 0))
    }
    
}

// MARK: ReportUserAlertVCDelegate Methods
extension ChatUserListVC: ReportUserAlertVCDelegate {
    
    func handleReportUserUpdateButtonTap(sender: UIButton, text: String) {
        var user: Users?
        switch self.listType {
        case .CHATS:
            user = self.saveDataArray[sender.tag].getFirstChatUser()?.user
        case .GROUP:
            user = nil
        case .ARCHIVE:
            user = self.archiveChats[sender.tag].getFirstChatUser()?.user
        }
        guard let user = user else { return }
        self.reportUser(user: user.user_id ?? "", text: text)
    }
    
}
