//
//  ConnectToSensorViewController.swift
//  MyTatvaCare
//
//  Created by Nirav Ramani on 08/05/25.
//

import UIKit
import AVFoundation
class ConnectToSensorViewController: UIViewController {
    let viewModel = FinalViewModel()
    
    @IBOutlet weak var contactSupport: CustomOverlayButton!
    @IBOutlet weak var customTopView: CustomTopUIView!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var bottomButton: CustomOverlayButton!
    
    enum enumTableSection: Int, CaseIterable {
        case details
        case success
        case error
    }
    
    enum enumTableRow: Int, CaseIterable {
        case separator
        case verticalLabel
        case image
        case camera
    }
    
    enum enumSuccessTableRow: Int, CaseIterable {
        case success
        case note
    }
    
    enum enumFailureTableRow: Int, CaseIterable {
        case failAnimation
        case details
        case image
        case watchVideo
    }
    
    enum enumScreenType {
        case camera
        case success
        case error
    }
    
    var isFromReconnect: Bool = false
    var connectedTime: Date?
    var connected:(()->())?
    var screenType: enumScreenType = .camera
    var isCodeDetected = false
    var isPermissionGiven: Bool = false
    let manager = KLTBluetoothManager.shared()
    let debouncer = EnumDebouncer<CGMConnectionStatus>()
    var deviceVerificationErrorMessage: String? = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        setupLayout()
    }
    
    func setupLayout() {
        manager?.addObserver(self, forKeyPath: "status", options: [.new], context: nil)
        
        
        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 payload = [
            "status": "cgm_permissions_proceed_clicked",
        ]

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

                NotificationCenter.default.post(
                    name: Notification.Name("cgmretryconnectsensorclicked"),
                    object: nil,
                    userInfo: payload
                )
                
                // Reset to camera mode for re-scanning
                self.isCodeDetected = false
                self.deviceVerificationErrorMessage = nil
                self.screenType = .camera
                self.tableView.reloadData()
                self.contactSupport.isHidden = true
                self.bottomButton.labelText = "Proceed"
                self.bottomButton.disable()
            } else {
                let payload = [
                    "status": "cgm_connect_sensor_proceed_clicked",
                ]

                NotificationCenter.default.post(
                    name: Notification.Name("cgmconnectsensorproceedclicked"),
                    object: nil,
                    userInfo: payload
                )
            
                let isForReconnect = UserDefaults.standard.bool(forKey: "isForReconnect")
                if isForReconnect{
                    let vc = AttachTransmitterViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
                    self.navigationController?.pushViewController(vc, animated: false)
                } else {
                    let vc = PutOnTheSensorViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
                    self.navigationController?.pushViewController(vc, animated: false)
                }
            }
         
        }
        
        customTopView.onDemoTapped = {
            let isForReconnect = UserDefaults.standard.bool(forKey: "isForReconnect")
            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: 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)
        }
        checkCameraPermission()
        bottomButton.disable()
    }
    
    func checkCameraPermission() {
        let status = AVCaptureDevice.authorizationStatus(for: .video)
        
        switch status {
        case .authorized:
            self.isPermissionGiven = true
            print("Camera access is authorized")
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: .video) { granted in
                if granted {
                    self.isPermissionGiven = true
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
                    print("Camera access granted")
                } else {
                    print("Camera access denied")
                    self.showCameraAccessAlert()
                }
            }
        case .denied, .restricted:
            print("Camera access denied or restricted")
            self.showCameraAccessAlert()
        @unknown default:
            self.showCameraAccessAlert()
            print("Unknown camera authorization status")
        }
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
        
    }
    
    func showCameraAccessAlert() {
        let alert = UIAlertController(
            title: "Camera Access Needed",
            message: "Please enable camera access in Settings to use this feature.",
            preferredStyle: .alert
        )
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { _ in
            if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
                UIApplication.shared.open(settingsURL)
            }
        })
        
        DispatchQueue.main.async {
            self.present(alert, animated: true)
        }
    }
    
    func connectSensor(value: String, controller: ConnectToSensorViewController) {
        UserDefaults.standard.set(value, forKey: "sensorId")
        
        var isMatch = false
        
        var regex = #"^[A-Z0-9][0-9](0[1-9]|[1-9][0-9]|[A-Z][1-9A-Z])(00[1-9]|0[1-9][0-9]|[1-9][0-9][0-9]){2}[0-9]{4,5}[0-9A-Z]{3}$"#
        var predicate = NSPredicate(format: "SELF MATCHES %@", regex)
        
        if predicate.evaluate(with: value) {
            isMatch = true
        } else {
            regex = #"^[A-Z1-9][1-9][A-Z0-9][0-9](0[1-9]|[1-9][0-9]|[A-Z][1-9A-Z])(00[1-9]|0[1-9][0-9]|[1-9][0-9][0-9]){2}[0-9]{6}[0-9A-Z]{3}$"#
            predicate = NSPredicate(format: "SELF MATCHES %@", regex)
            if predicate.evaluate(with: value) {
                isMatch = true
            }
        }
        
        if isMatch {
            let data = AlgorithmTools.decodeCT(value)
            
            if data.k > 0 || data.r > 0 {
                //KLTLocalSettingManager.shareInstance.deviceInfoSensor = value
                UserDefaults.standard.set(data.k, forKey: "algo_k")
                UserDefaults.standard.set(data.r, forKey: "algo_r")
                UserDefaults.standard.synchronize()
                
                let lastConnectCgm = UserDefaults.standard.string(forKey: "lastConnectCgm") ?? ""
                
                if lastConnectCgm.lowercased() == "diasens" {
                    // Diasens user - validate sensor via API before connecting
                    validateDiasensSensor(sensorId: value)
                } else {
                    // Non-Diasens user - proceed directly
                    viewModel.debouncer.update(with: .connected)
                    self.showConfirmInsulinUser()
                }
                return
            }
        }
        
        //controller.resumeScanning()
    }
    
    func validateDiasensSensor(sensorId: String) {
        API.shared.verifyDevice(
            sensorId: sensorId,
            onSuccess: { [weak self] code, dataValue, msg in
                guard let self = self else { return }
                
                if code == 1 && dataValue == true {
                    // Device verification successful - proceed with connection
                    print("Device verification successful for sensor: \(sensorId)")
                    self.viewModel.debouncer.update(with: .connected)
                    self.showConfirmInsulinUser()
                } else if code == 1 && dataValue == false {
                    // Device verification failed - show API msg in red (with fallback)
                    print("Device verification failed: \(msg)")
                    let errorMessage = msg.isEmpty ? "This is not a Diasens CGM sensor. Please connect a Diasens sensor to continue." : msg
                    self.showDeviceVerificationError(message: errorMessage)
                } else {
                    // code 0 or unexpected - show Try Again
                    print("Device verification error, code: \(code)")
                    self.showDeviceVerificationError(message: "Try Again")
                }
            },
            onFailure: { [weak self] in
                print("Device verification API call failed")
                self?.showDeviceVerificationError(message: "Try Again")
            }
        )
    }
    
    func showDeviceVerificationError(message: String) {
        isCodeDetected = false
        deviceVerificationErrorMessage = message
        screenType = .error
        tableView.reloadData()
        contactSupport.isHidden = false
        bottomButton.labelText = "Retry"
        bottomButton.hideRightArrow()
        bottomButton.enable()
        
        // Post notification for sensor connection failed event
        let payload: [String: String] = [
            "status": "cgm_sensor_connection_failed",
            "error_description": message
        ]
        NotificationCenter.default.post(
            name: Notification.Name("cgmsensorconnectionfailed"),
            object: nil,
            userInfo: payload
        )
    }
    
    func connectThisSensor() {
        // Connect the transmitter
        manager?.connectPeripheral(manager?.readyToConnectedPeripheral)
    }
    
    func showConfirmInsulinUser() {
        let typeOfDiabetes = UserDefaults.standard.object(forKey: "profilePatientType") as? NSNumber
        
        if let diabetesType = typeOfDiabetes {
            // LocalizedString(@"user_diabete_no") index is 0
            if diabetesType.intValue == 0 {
                // No
                UserDefaults.standard.set(2, forKey: "algo_user_type")
            } else {
                // Yes
                UserDefaults.standard.set(1, forKey: "algo_user_type")
            }
        } else {
            // Not selected
            UserDefaults.standard.set(0, forKey: "algo_user_type")
        }
        
        UserDefaults.standard.synchronize() // Optional, rarely needed in modern iOS
        
        connectThisSensor()
    }
    
    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 = newValue
                let btStatus: BluetoothManagerStatus = BluetoothManagerStatus(rawValue: newValue) ?? .scanStart
                
                if btStatus == .initialStart {
                    self.connectedTime = Date()
                    print("Success")
                    
                    let payload = [
                        "status": "cgm_sensor_connection_successful",
                    ]

                    NotificationCenter.default.post(
                        name: Notification.Name("cgmsensorconnectionsuccessful"),
                        object: nil,
                        userInfo: payload
                    )
            
                    screenType = .success
                    tableView.reloadData()
                    bottomButton.enable()
                    if self.isFromReconnect {
                        let _ = FinalViewModelManager.shared
                        NotificationCenter.default.post(name: Notification.Name("cgmDeviceEvent"), object: nil, userInfo: ["a":"a"])
                        
                        let vc = AttachTransmitterViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
                        self.navigationController?.pushViewController(vc, animated: false)
                        
//                        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 {
                        let vc = PutOnTheSensorViewController.instantiate(fromStoryboard: Enum_stroyboard.Main.rawValue)
                        self.navigationController?.pushViewController(vc, animated: false)
                    }
                } else if btStatus == .closed || btStatus == .modifyVoltageFailed {
                    var errorDescription = ""
                    var errorCode = ""

                    switch btStatus {
                    case .closed:
                        errorDescription = "Sensor connection was closed"
                        errorCode = "SENSOR_CONNECTION_CLOSED"
                    case .modifyVoltageFailed:
                        errorDescription = "Failed to modify sensor voltage"
                        errorCode = "SENSOR_MODIFY_VOLTAGE_FAILED"
                    default:
                        break
                    }

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

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

                    navigationController?.popToRootViewController(animated: true)
                }

            }
        } else if keyPath == "status", context != nil {
            if let playerItem = object as? AVPlayerItem {
                if playerItem.status == .readyToPlay {
                    if UserDefaults.standard.integer(forKey: "bgmode") == 0 {
                        // player?.play()
                    }
                }
            }
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
    
}

extension ConnectToSensorViewController: UITableViewDelegate, UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return enumTableSection.allCases.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch enumTableSection(rawValue: section)! {
        case .details:
            return (screenType == .camera) ? enumTableRow.allCases.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 * 120 / 390) + 40
            case .camera:
                return 220
            default:
                return UITableView.automaticDimension
            }
        case .error:
            switch enumFailureTableRow(rawValue: indexPath.row) {
            case .failAnimation:
                // Reduced height for validation API error, normal for other errors
                return (deviceVerificationErrorMessage != nil) ? 80 : 120
            case .image:
                return (UIScreen.main.bounds.width * 120 / 390) + 20
            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 3"
                cell.label2.text = "Connect to your Sensor"
                cell.label3.text = "Scan the QR on the back of the sensor to connect with the GoodFlip app"
                return cell
            case .image:
                let cell: ImageTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.displayImageView.image = loadImage(named: "flip_the_reference")
                cell.displayImageView.contentMode = .scaleAspectFill
                cell.displayImageView.isHidden = false
                cell.cameraView.isHidden = true
                return cell
            case .camera:
                let cell: ImageTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.displayImageView.contentMode = .scaleAspectFill
                cell.displayImageView.isHidden = true
                cell.cameraView.isHidden = false
                if isPermissionGiven {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                        cell.setupQRView()
                        cell.scannerView?.onCodeDetected = { data in
                            if !self.isCodeDetected {
                                self.isCodeDetected = true
                                self.connectSensor(value: data, controller: self)
                            }
                        }
                    }
                }
                return cell
            }
        case .success:
            switch enumSuccessTableRow(rawValue: indexPath.row)! {
            case .success:
                let cell: ConnectSuccessTVC = tableView.dequeueReusableCell(for: indexPath)
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = "dd-MM-yyyy hh:mm a"
                dateFormatter.timeZone = TimeZone.current
                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.isHidden = true
                cell.labelTitle.text = "Sensor Connected Successfully"
                cell.setImageForCGM()
                return cell
                
            case .note:
                let cell: NoteTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.setImportantNote(isFromSuccessConnection: true)
                return cell
            }
        case .error:
            switch enumFailureTableRow(rawValue: indexPath.row)! {
            case .failAnimation:
                let cell: ImageTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.displayImageView.loadGif(named: "failure")
                cell.bottomConstraint.constant = 11
                // Hide camera view to prevent it from overlapping error content (cell reuse)
                cell.cameraView.isHidden = true
                cell.displayImageView.isHidden = false
                // Scale down only for validation API error (65% of original size)
                if deviceVerificationErrorMessage != nil {
                    cell.displayImageView.contentMode = .scaleAspectFit
                    cell.displayImageView.clipsToBounds = true
                    cell.displayImageView.transform = CGAffineTransform(scaleX: 0.65, y: 0.65)
                } else {
                    cell.displayImageView.transform = .identity
                }
                return cell
            case .details:
                let cell: VerticalLabelsTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.topConstraint.constant = 0
                cell.label1.isHidden = true
                if let verificationError = deviceVerificationErrorMessage {
                    cell.label2.text = verificationError
                    cell.label2.textColor = .red
                    // Use smaller font for validation API error message (default title is 32pt)
                    cell.label2.font = FontManager.font(ofSize: 16, weight: .medium)
                    cell.label2.numberOfLines = 0
                    cell.label3.text = ""
                } else {
                    cell.label2.text = "Unable to det﻿ect sensor"
                    // Restore default title font for normal error
                    cell.label2.font = FontManager.title
                    cell.label2.textColor = CustomColor.shared.primaryBlack
                    cell.label3.text = "Make sure there is proper lighting in the room"
                }
                return cell
            case .image:
                let cell: ImageTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.topConstraint.constant = 0
                cell.displayImageView.image = loadImage(named: "flip_the_reference")
                cell.displayImageView.contentMode = .scaleAspectFill
                // Hide camera view to prevent it from overlapping error content (cell reuse)
                cell.cameraView.isHidden = true
                cell.displayImageView.isHidden = false
                return cell
            case .watchVideo:
                let cell: WatchVideoTVC = tableView.dequeueReusableCell(for: indexPath)
                cell.onPlayVideo = {
                    let webVC = WebViewController()
                    webVC.modalPresentationStyle = .formSheet
                    webVC.videoURL = URL(string: qrScanFailed)
                    self.present(webVC, animated: true, completion: nil)
                }
                return cell
            }
        }
    }
}

