//
//  ConnectToTransmitterViewController.swift
//  MyTatvaCare
//
//  Created by Nirav Ramani on 07/05/25.
//

import UIKit
import CoreBluetooth
class ConnectToTransmitterViewController: UIViewController, KLTBluetoothDelegate {

    @IBOutlet weak var contactSupport: CustomOverlayButton!
    @IBOutlet weak var customTopView: CustomTopUIView!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var bottomButton: CustomOverlayButton!
    @IBOutlet weak var customStepProgressHeightConstraint: NSLayoutConstraint!
    @IBOutlet weak var customStepProgressBar: CustomStepProgressBar!
    
    enum enumTableSection: Int, CaseIterable {
        case details
        case listOfDevice
        case success
        case error
    }
    
    enum enumTableRow: Int, CaseIterable {
        case separator
        case verticalLabel
        case image
        case searchForDevice
    }
    
    enum enumSuccessTableRow: Int, CaseIterable {
        case success
        case importantNote
    }
    
    enum enumFailureTableRow: Int, CaseIterable {
        case failAnimation
        case details
        case podDetails
        case watchVideo
    }

    enum enumScreenType {
        case searching
        case listOfDevice
        case success
        case error
    }

    var screenType: enumScreenType = .searching
    var devices: [(peripheral: CBPeripheral,name: String)] = []
    @objc var isForReconnect: Bool = false
    var connectedTime: Date?
    
    var foundDevices: NSMutableArray = []
    let manager = KLTBluetoothManager.shared()
    private var bluetoothEnableObserver: NSObjectProtocol?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupLayout()
    }

    deinit {
        if let observer = bluetoothEnableObserver {
            NotificationCenter.default.removeObserver(observer)
        }
    }
    
    func setupLayout() {
        manager?.addObserver(self, forKeyPath: "status", options: [.new], context: nil)

        //BluetoothManager.shared.delegate = self
        manager?.bluetoothDelegate = self

        // FIX: On first launch BLE state can be "unknown" so startScan aborts silently.
        // Listen for BluetoothEnable and start scan as soon as BLE is powered on.
        bluetoothEnableObserver = NotificationCenter.default.addObserver(
            forName: NSNotification.Name("BluetoothEnable"),
            object: nil,
            queue: .main
        ) { [weak self] notification in
            guard let self = self else { return }
            let isOn = (notification.object as? NSNumber)?.boolValue ?? false
            if isOn && self.screenType == .searching {
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                    self.manager?.startScan()
                }
            }
        }

        manager?.startScan()
        //BluetoothManager.shared.startScanning()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.registerNibs([VerticalLabelsTVC.self,
                                SeparatorTVC.self,
                                ImageTVC.self,
                                SearchDeviceTVC.self,
                                ConnectDeviceTVC.self,
                                ConnectSuccessTVC.self,
                                NoteTVC.self,
                                PodDetailsTVC.self,
                                WatchVideoTVC.self])
        tableView.reloadData()
        contactSupport.isHidden = screenType != .error
        contactSupport.labelText = "Contact Support"
        contactSupport.setBorderOnly()
        contactSupport.buttonTapCallback = {
            let vc = ChatWithExpertViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
            self.navigationController?.pushViewController(vc, animated: false)
        }
        
        let payload = [
            "status": "cgm_connect_transmitter_landing",
        ]

        NotificationCenter.default.post(
            name: Notification.Name("cgmconnecttransmitterlanding"),
            object: nil,
            userInfo: payload
        )
        
        bottomButton.labelText = screenType == .error ? "Retry" : "Proceed"
        
        if screenType == .searching {
            bottomButton.hideRightArrow()
        }
        bottomButton.buttonTapCallback = {
            if self.isForReconnect {
                if  self.bottomButton.labelText == "Retry" {
                    let payload = [
                        "status": "cgm_retry_connect_transmitter_clicked",
                    ]

                    NotificationCenter.default.post(
                        name: Notification.Name("cgmretryconnecttransmitterclicked"),
                        object: nil,
                        userInfo: payload
                    )
                    
                    
                    self.manager?.bluetoothDelegate = self
                    self.manager?.startScan()
                    self.screenType = .searching
                    self.tableView.reloadData()
                    self.bottomButton.hideRightArrow()
                } else {
                    let vc = ConnectToSensorViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
                    vc.connected = {
                        //self.showConfirmInsulinUser()
                    }
                    vc.isFromReconnect = true
                    self.navigationController?.pushViewController(vc, animated: false)
                }
               
//                NotificationCenter.default.post(name: Notification.Name("cgmDeviceEvent"), object: nil, userInfo: ["a":"a"])
//                if let rootVC = UIApplication.shared.connectedScenes
//                    .compactMap({ ($0 as? UIWindowScene)?.windows.first?.rootViewController })
//                    .first {
//                    rootVC.dismiss(animated: true, completion: nil)
//                } else if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
//                    rootViewController.dismiss(animated: true, completion: nil)
//                }
            } else {
                if self.screenType == .error {
                    self.manager?.bluetoothDelegate = self
                    self.manager?.startScan()
                    self.bottomButton.disable()
                    self.screenType = .searching
                    self.tableView.reloadData()
                } else {
                    let vc = ConnectToSensorViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
                    vc.connected = {
                        //self.showConfirmInsulinUser()
                    }
                    self.navigationController?.pushViewController(vc, animated: false)
                }
            }
        }

        customTopView.onDemoTapped = {
            let payload = [
                "status": "cgm_watch_demo_clicked"
            ]
            
            NotificationCenter.default.post(
                name: Notification.Name("cgmwatchdemoclicked"),
                object: nil,
                userInfo: payload
            )
            
            let webVC = WebViewController()
            webVC.modalPresentationStyle = .formSheet
            webVC.videoURL = URL(string: self.isForReconnect == true ? reconnectionwatchCGMVideo : watchCGMVideo)
            self.present(webVC, animated: true, completion: nil)
        }
        
        customTopView.onCloseTapped = {
            let vc = ExitJourneyViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
            vc.modalPresentationStyle = .overFullScreen
            self.present(vc, animated: true, completion: nil)
        }
        customTopView.onWhatsAppTapped = {
            let vc = ChatWithExpertViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
            self.navigationController?.pushViewController(vc, animated: false)
        }
        
        if isForReconnect {
            //customTopView.showOnlyClose()
            //customStepProgressBar.isHidden = true
            //customStepProgressHeightConstraint.constant = 0
            bottomButton.labelText = "Complete"
            bottomButton.showRightArrow()
           
        }
        bottomButton.disable()
    }

    func onFindDevices(_ array: NSMutableArray!, connectedDevice peripheral: CBPeripheral!) {
        if array.count > 0 {
            let payload = [
                "status": "cgm_transmitter_detected",
            ]

            NotificationCenter.default.post(
                name: Notification.Name("cgmtransmitterdetected"),
                object: nil,
                userInfo: payload
            )
            bottomButton.labelText = screenType == .error ? "Retry" : "Proceed"
            self.foundDevices = array
            self.screenType = .listOfDevice
            self.tableView.reloadData()
        }
    }
    
    override func observeValue(forKeyPath keyPath: String?,
                               of object: Any?,
                               change: [NSKeyValueChangeKey : Any]?,
                               context: UnsafeMutableRawPointer?) {
        if keyPath == "status" && context == nil {
            if let newValue = change?[.newKey] as? Int {
                let btStatus: BluetoothManagerStatus = BluetoothManagerStatus(rawValue: newValue) ?? .scanStart

                if btStatus == .timeOut ||
                    btStatus == .disconnected ||
                    btStatus == .handshakeFail ||
                    btStatus == .selfCheckFail ||
                    btStatus == .closed ||
                    btStatus == .modifyVoltageFailed ||
                    btStatus == .sensorLostPower ||
                    btStatus == .bindWatchTimeOut {

                    var errorDescription = ""
                    var errorCode = ""

                    switch btStatus {
                    case .timeOut:
                        errorDescription = "Connection timed out"
                        errorCode = "BT_TIMEOUT"

                    case .disconnected:
                        errorDescription = "Device disconnected unexpectedly"
                        errorCode = "BT_DISCONNECTED"

                    case .handshakeFail:
                        errorDescription = "Handshake with transmitter failed"
                        errorCode = "BT_HANDSHAKE_FAIL"

                    case .selfCheckFail:
                        errorDescription = "Self-check failed"
                        errorCode = "BT_SELF_CHECK_FAIL"

                    case .closed:
                        errorDescription = "Bluetooth manager closed"
                        errorCode = "BT_CLOSED"

                    case .modifyVoltageFailed:
                        errorDescription = "Voltage adjustment failed"
                        errorCode = "BT_MODIFY_VOLTAGE_FAIL"

                    case .sensorLostPower:
                        errorDescription = "Sensor lost power"
                        errorCode = "BT_SENSOR_LOST_POWER"

                    case .bindWatchTimeOut:
                        errorDescription = "Binding with watch timed out"
                        errorCode = "BT_BIND_TIMEOUT"

                    default:
                        break
                    }

                    let payload = [
                        "status": "cgm_transmitter_detection_failed",
                        "error_description": errorDescription,
                        "error_code": errorCode
                    ]

                    NotificationCenter.default.post(
                        name: Notification.Name("cgmtransmitterdetectionfailed"),
                        object: nil,
                        userInfo: payload
                    )

                    self.screenType = .error
                    bottomButton.labelText = screenType == .error ? "Retry" : "Proceed"
                    bottomButton.enable()
                    self.tableView.reloadData()
                }
            }

        } else if keyPath == "status", context != nil {
           
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
    
    func sensorForceEnd() {
        if let manager = manager {
            if ((manager.connectedPeripheral) != nil) {
                if (manager.status == .resendEnd || manager.status == .getGLU || manager.status == .initialStart) {
                    manager.closeBleSensor()
                }
            } else {
                if (manager.currentDevice != nil) {
                    manager.forceEndBleSensor()
                }
            }
        }
    }
}

extension ConnectToTransmitterViewController: UITableViewDelegate, UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        self.contactSupport.isHidden = screenType != .error
        
        return enumTableSection.allCases.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch enumTableSection(rawValue: section)! {
        case .details:
            return (screenType == .searching || screenType == .listOfDevice) ? enumTableRow.allCases.count : 0
        case .listOfDevice:
            return screenType == .listOfDevice ? foundDevices.count : 0
        case .success:
            return screenType == .success ? enumSuccessTableRow.allCases.count : 0
        case .error:
            return screenType == .error ? enumFailureTableRow.allCases.count : 0
        }
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        switch enumTableSection(rawValue: indexPath.section)! {
        case .details:
            switch enumTableRow(rawValue: indexPath.row) {
            case .image:
                return (UIScreen.main.bounds.width * 660 / 1560) + 40
            case .searchForDevice:
                return screenType == .searching ? UITableView.automaticDimension : 0
            default:
                return UITableView.automaticDimension
            }
        case .error:
            switch enumFailureTableRow(rawValue: indexPath.row) {
            case .failAnimation:
                return 120
            case .podDetails:
                return 142
            default:
                return UITableView.automaticDimension
            }
        case .success:
            switch enumSuccessTableRow(rawValue: indexPath.row) {
            case .importantNote:
              //  if isForReconnect { return 0 }
                return UITableView.automaticDimension
            default:
                return UITableView.automaticDimension
            }
        default:
            return UITableView.automaticDimension
        }
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch enumTableSection(rawValue: indexPath.section)! {
        case .details:
            switch enumTableRow(rawValue: indexPath.row)! {
            case .separator:
                let cell: SeparatorTVC = tableView.dequeueReusableCell(for: indexPath)
                return cell
            case .verticalLabel:
                let cell: VerticalLabelsTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.label1.text = "STEP 2"
                cell.label1.isHidden = isForReconnect
                cell.label2.text = "Connect to your Transmitter"
                cell.label3.text = "Remove the transmitter from the charging pod and our app will detect it"
                return cell
            case .image:
                let cell: ImageTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.displayImageView.image = loadImage(named: "Take_out_transmitter")
                cell.displayImageView.contentMode = .scaleAspectFill
                cell.displayImageView.isHidden = false
                return cell
            case .searchForDevice:
                let cell: SearchDeviceTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.labelDesc.text = "Searching for your device..."
                cell.imageViewLeft.loadGif(named: "searching")
                return cell
            }
        case .listOfDevice:
            let cell: ConnectDeviceTVC = tableView.dequeueReusableCell(for: indexPath)
            cell.button.hideRightArrow()
            
        
            let peripheral = foundDevices[indexPath.row] as! CBPeripheral
            let device = KLTDatabaseHandler.shared().queryDevice(withId: peripheral.identifier.uuidString)
            let name = device?.advertise?.localName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
            cell.labelDesc.text = name.isEmpty ? "Unknown" : name
            
            //cell.labelDesc.text = "Sno:\(devices[indexPath.row].name)"
            cell.button.buttonTapCallback = {
                
                if self.isForReconnect {
                    self.sensorForceEnd()
                }
                
                if !KLTLocalSettingManager.shareInstance().canConnectOtherDevice {
                    return
                }
                
                self.manager?.stopScan()
                if self.foundDevices.count > indexPath.row {
                    let peripheral = self.foundDevices[indexPath.row] as! CBPeripheral
                    if let device = KLTDatabaseHandler.shared().queryDevice(withId: peripheral.identifier.uuidString) {
                        let payload = [
                            "status": "cgm_transmitter_connection_successful",
                        ]

                        NotificationCenter.default.post(
                            name: Notification.Name("cgmtransmitterconnectionsuccessful"),
                            object: nil,
                            userInfo: payload
                        )
                        
                        //let snLocalName = device.advertise?.localName?.trimmingCharacters(in: .whitespacesAndNewlines)
                        self.connectedTime = Date()
                        print("Connected device", device)
                        self.manager?.readyToConnectedPeripheral = peripheral
                        self.screenType = .success
                        //API.shared.sendStatus(status: .connected)
                        self.bottomButton.enable()
                        tableView.reloadData()
                    } else {
                        let errorPayload = [
                               "status": "cgm_transmitter_detection_failed",
                               "error_description": "Device not found in database",
                               "error_code": "BT_DEVICE_NOT_IN_DB"
                           ]
                           NotificationCenter.default.post(
                               name: Notification.Name("cgmtransmitterdetectionfailed"),
                               object: nil,
                               userInfo: errorPayload
                           )
                    }
                }
            }
            return cell
        case .success:
            switch enumSuccessTableRow(rawValue: indexPath.row)! {
            case .success:
                let cell: ConnectSuccessTVC = tableView.dequeueReusableCell(for: indexPath)
                if let device = KLTDatabaseHandler.shared().queryDevice(withId: manager?.readyToConnectedPeripheral.identifier.uuidString) {
                    let name = device.advertise?.localName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
                    let dateFormatter = DateFormatter()
                    dateFormatter.dateFormat = "dd-MM-yyyy hh:mm a"
                    dateFormatter.timeZone = TimeZone.current
                    cell.parentImageView.loadGif(named: "success")
                    if let connectedTime = connectedTime {
                        // Convert the Date to a String
                        let dateString = dateFormatter.string(from: connectedTime)
                        cell.labelDate.text = "Connected on \(String(describing: dateString))"
                    } else {
                        cell.labelDate.text = ""
                    }
                    cell.labelDesc.text = "Sno: \(name)"
                }
                return cell
            case .importantNote:
                let cell: NoteTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.setImportantNote(isFromSuccessConnection: false)
                return cell
            }
        case .error:
            switch enumFailureTableRow(rawValue: indexPath.row)! {
            case .failAnimation:
                let cell: ImageTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.bottomConstraint.constant = 11
                cell.gifView.isHidden = false
                cell.gifView.loadGif(named: "failure")
                cell.displayImageView.isHidden = true
                return cell
            case .details:
                let cell: VerticalLabelsTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.topConstraint.constant = 0
                cell.label1.isHidden = true
                cell.label2.text = "Unable ﻿to detect transmitter"
                cell.label3.text = "Make sure your transmitter is fully charges is placed out of the charging pod"
                return cell
            case .podDetails:
                let cell: PodDetailsTVC = tableView.dequeueReusableCell(for: indexPath)
                return cell
            case .watchVideo:
                let cell: WatchVideoTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.onPlayVideo = {
                    let webVC = WebViewController()
                    webVC.modalPresentationStyle = .formSheet 
                    webVC.videoURL = URL(string: connectionJourneyError)
                    self.present(webVC, animated: true, completion: nil)
                }
                return cell
            }
        }
    }
    
}
