//
//  LoginQuestionViewController.swift
//  RoderickRalph
//
//  Created by AI Assistant on 2025/09/16.
//

import Foundation
import UIKit
//import sys/utsname.h

class EntryGateController: UIViewController, RoutePickerAgent {
    
    // MARK: - API Endpoints
    private let pathGetRoutes = "/ditch/list"
    private let pathSetRoute = "/wx/iosLogin"
    
    // MARK: - UI Components
    private let backdropImage: UIImageView = {
        let imageView = UIImageView()
        imageView.image = UIImage(named: "res001")
        imageView.contentMode = .scaleAspectFill
        imageView.translatesAutoresizingMaskIntoConstraints = false
        return imageView
    }()
    
    private let enterBtn: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("登录", for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 24)
        button.backgroundColor = .white
        button.layer.cornerRadius = 25
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    private let routeBtn: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("渠道 ▼", for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
        button.backgroundColor = .white
        button.layer.cornerRadius = 20
        button.contentHorizontalAlignment = .center
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    // MARK: - Properties
    private var routePopup: RoutePickerView?
    
    // MARK: - Device Model Helper
    private func deviceModel() -> String {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
        
        return deviceNameFor(identifier)
    }
    
    private func deviceNameFor(_ identifier: String) -> String {
        switch identifier {
        // iPhone
        case "iPhone1,1": return "iPhone"
        case "iPhone1,2": return "iPhone 3G"
        case "iPhone2,1": return "iPhone 3GS"
        case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4"
        case "iPhone4,1": return "iPhone 4S"
        case "iPhone5,1", "iPhone5,2": return "iPhone 5"
        case "iPhone5,3", "iPhone5,4": return "iPhone 5c"
        case "iPhone6,1", "iPhone6,2": return "iPhone 5s"
        case "iPhone7,2": return "iPhone 6"
        case "iPhone7,1": return "iPhone 6 Plus"
        case "iPhone8,1": return "iPhone 6s"
        case "iPhone8,2": return "iPhone 6s Plus"
        case "iPhone8,4": return "iPhone SE"
        case "iPhone9,1", "iPhone9,3": return "iPhone 7"
        case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus"
        case "iPhone10,1", "iPhone10,4": return "iPhone 8"
        case "iPhone10,2", "iPhone10,5": return "iPhone 8 Plus"
        case "iPhone10,3", "iPhone10,6": return "iPhone X"
        case "iPhone11,2": return "iPhone XS"
        case "iPhone11,4", "iPhone11,6": return "iPhone XS Max"
        case "iPhone11,8": return "iPhone XR"
        case "iPhone12,1": return "iPhone 11"
        case "iPhone12,3": return "iPhone 11 Pro"
        case "iPhone12,5": return "iPhone 11 Pro Max"
        case "iPhone12,8": return "iPhone SE (2nd generation)"
        case "iPhone13,1": return "iPhone 12 mini"
        case "iPhone13,2": return "iPhone 12"
        case "iPhone13,3": return "iPhone 12 Pro"
        case "iPhone13,4": return "iPhone 12 Pro Max"
        case "iPhone14,2": return "iPhone 13"
        case "iPhone14,3": return "iPhone 13 mini"
        case "iPhone14,4": return "iPhone 13 Pro"
        case "iPhone14,5": return "iPhone 13 Pro Max"
        case "iPhone14,6": return "iPhone SE (3rd generation)"
        case "iPhone14,7": return "iPhone 14"
        case "iPhone14,8": return "iPhone 14 Plus"
        case "iPhone15,2": return "iPhone 14 Pro"
        case "iPhone15,3": return "iPhone 14 Pro Max"
        case "iPhone15,4": return "iPhone 15"
        case "iPhone15,5": return "iPhone 15 Plus"
        case "iPhone16,1": return "iPhone 15 Pro"
        case "iPhone16,2": return "iPhone 15 Pro Max"
        case "iPhone17,1": return "iPhone 16 Pro"
        case "iPhone17,2": return "iPhone 16 Pro Max"
        case "iPhone17,3": return "iPhone 16"
        case "iPhone17,4": return "iPhone 16 Plus"
        case "iPhone17,5": return "iPhone 16e"
        case "iPhone18,1": return "iPhone 17 Pro"
        case "iPhone18,2": return "iPhone 17 Pro Max"
        case "iPhone18,3": return "iPhone 17"
        case "iPhone18,4": return "iPhone Air"

        // iPad
        case "iPad1,1": return "iPad"
        case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4": return "iPad 2"
        case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad (3rd generation)"
        case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad (4th generation)"
        case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air"
        case "iPad5,3", "iPad5,4": return "iPad Air 2"
        case "iPad6,11", "iPad6,12": return "iPad (5th generation)"
        case "iPad7,5", "iPad7,6": return "iPad (6th generation)"
        case "iPad7,11", "iPad7,12": return "iPad (7th generation)"
        case "iPad11,6", "iPad11,7": return "iPad (8th generation)"
        case "iPad12,1", "iPad12,2": return "iPad (9th generation)"
        case "iPad13,18", "iPad13,19": return "iPad (10th generation)"
        case "iPad6,7", "iPad6,8": return "iPad Pro (12.9-inch)"
        case "iPad6,3", "iPad6,4": return "iPad Pro (9.7-inch)"
        case "iPad7,1", "iPad7,2": return "iPad Pro (12.9-inch) (2nd generation)"
        case "iPad7,3", "iPad7,4": return "iPad Pro (10.5-inch)"
        case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4": return "iPad Pro (11-inch)"
        case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8": return "iPad Pro (12.9-inch) (3rd generation)"
        case "iPad8,9", "iPad8,10": return "iPad Pro (11-inch) (2nd generation)"
        case "iPad8,11", "iPad8,12": return "iPad Pro (12.9-inch) (4th generation)"
        case "iPad13,4", "iPad13,5", "iPad13,6", "iPad13,7": return "iPad Pro (11-inch) (3rd generation)"
        case "iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11": return "iPad Pro (12.9-inch) (5th generation)"
        case "iPad14,1", "iPad14,2": return "iPad mini (6th generation)"
        case "iPad14,3", "iPad14,4": return "iPad Pro (11-inch) (4th generation)"
        case "iPad14,5", "iPad14,6": return "iPad Pro (12.9-inch) (6th generation)"
        case "iPad14,8", "iPad14,9": return "iPad Air (11-inch) (6th generation)"
        case "iPad14,10", "iPad14,11": return "iPad Air (13-inch) (6th generation)"
        case "iPad15,3", "iPad15,4": return "iPad Air (11-inch) (7th generation)"
        case "iPad15,5", "iPad15,6": return "iPad Air (13-inch) (7th generation)"
        case "iPad15,7", "iPad15,8": return "iPad (11th generation)"
        case "iPad16,1", "iPad16,2": return "Pad mini (7th generation)"
        case "iPad16,3", "iPad16,4": return "iPad Pro (11-inch) (5th generation)"
        case "iPad16,5", "iPad16,6": return "iPad Pro (12.9-inch) (7th generation)"

        // iPod
        case "iPod1,1": return "iPod touch"
        case "iPod2,1": return "iPod touch (2nd generation)"
        case "iPod3,1": return "iPod touch (3rd generation)"
        case "iPod4,1": return "iPod touch (4th generation)"
        case "iPod5,1": return "iPod touch (5th generation)"
        case "iPod7,1": return "iPod touch (6th generation)"
        case "iPod9,1": return "iPod touch (7th generation)"
        
        // Simulator
        case "i386", "x86_64", "arm64": return "Simulator"
        
        default: return identifier
        }
    }
    private var channels: [Channel] = []
    private var selectedChannel: Channel?
    private var loginUserInfo: LoginUserInfo?
    
    // System loading overlay
    private var loadingOverlay: UIView?
    private var loadingSpinner: UIActivityIndicatorView?
    
    // MARK: - Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        buildUI()
        applyLayout()
        wireActions()
        
        // Hide navigation bar
        navigationController?.setNavigationBarHidden(true, animated: false)
        
        // Fetch channel list on load
        fetchRoutes()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: animated)
    }
    
    // MARK: - UI Setup
    private func buildUI() {
        view.addSubview(backdropImage)
        view.addSubview(enterBtn)
        view.addSubview(routeBtn)
    }
    
    private func applyLayout() {
        NSLayoutConstraint.activate([
            // Background image - fill entire screen
            backdropImage.topAnchor.constraint(equalTo: view.topAnchor),
            backdropImage.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            backdropImage.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            backdropImage.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            
            // Login button - center of screen
            enterBtn.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            enterBtn.centerYAnchor.constraint(equalTo: view.centerYAnchor,constant: 50),
            enterBtn.widthAnchor.constraint(equalToConstant: 200),
            enterBtn.heightAnchor.constraint(equalToConstant: 50),
            
            // Channel select button - below login button
            routeBtn.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            routeBtn.topAnchor.constraint(equalTo: enterBtn.bottomAnchor, constant: 30),
            routeBtn.widthAnchor.constraint(equalToConstant: 200),
            routeBtn.heightAnchor.constraint(equalToConstant: 40)
        ])
    }
    
    private func wireActions() {
        enterBtn.addTarget(self, action: #selector(didTapLogin), for: .touchUpInside)
        routeBtn.addTarget(self, action: #selector(didTapChannelPicker), for: .touchUpInside)
    }
    
    // MARK: - Actions
    @objc private func didTapLogin() {
        guard let channel = selectedChannel else {
            flashToast(message: "请先选择渠道")
            return
        }
        
        submitRoute(channel: channel)
    }
    
    @objc private func didTapChannelPicker() {
        guard !channels.isEmpty else {
            flashToast(message: "渠道列表为空，请稍后重试")
            fetchRoutes() // Retry fetching
            return
        }
        
        presentRoutePicker(channels: channels)
    }
    
    // MARK: - Channel Selection Flow
    private func fetchRoutes() {
        guard let url = URL(string: apiBaseURL + pathGetRoutes) else {
            print("[Channel] Invalid getQudaoList URL")
            return
        }
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let bodyParams: [String: Any] = ["appId": kTakuAppID]
        request.httpBody = try? JSONSerialization.data(withJSONObject: bodyParams, options: [])
        
        if let body = request.httpBody,
           let bodyString = String(data: body, encoding: .utf8) {
            print("[Channel] Request URL: \(url)")
            print("[Channel] Request Headers: \(request.allHTTPHeaderFields ?? [:])")
            print("[Channel] Request Body: \(bodyString)")
        }

        let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
            if let httpResponse = response as? HTTPURLResponse {
                print("[Channel] Response Code: \(httpResponse.statusCode)")
                print("[Channel] Response Headers: \(httpResponse.allHeaderFields)")
            }
            if let data = data, let responseString = String(data: data, encoding: .utf8) {
                print("[Channel] Response Body: \(responseString)")
            }
            if let error = error {
                print("[Channel] fetch error: \(error)")
                DispatchQueue.main.async { [weak self] in
                    self?.flashToast(message: "网络错误,请重新登录")
                }
                return
            }
            guard let data = data else { return }
            let channels = self?.decodeRoutes(from: data) ?? []
            DispatchQueue.main.async {
                if channels.isEmpty {
                    print("[Channel] No channels returned")
                    self?.flashToast(message: "没有渠道信息，请重新登录")
                } else {
                    self?.channels = channels
                    // Set first channel as default if none selected
                    if self?.selectedChannel == nil && !channels.isEmpty {
                        self?.selectedChannel = channels[0]
                        self?.refreshChannelTitle()
                    }
                }
            }
        }
        task.resume()
    }
    
    private func decodeRoutes(from data: Data) -> [Channel] {
        func normalizeArray(_ arr: [Any]) -> [Channel] {
            var result: [Channel] = []
            for (idx, item) in arr.enumerated() {
                if let dict = item as? [String: Any] {
                    let idAny = dict["id"] ?? dict["ditchId"] ?? dict["value"] ?? idx
                    let nameAny = dict["name"] ?? dict["ditchName"] ?? dict["label"] ?? "\(idAny)"
                    let idStr = String(describing: idAny)
                    let nameStr = String(describing: nameAny)
                    result.append(Channel(id: idStr, name: nameStr))
                } else if let str = item as? String {
                    result.append(Channel(id: str, name: str))
                } else if let num = item as? NSNumber {
                    let s = num.stringValue
                    result.append(Channel(id: s, name: s))
                }
            }
            return result
        }

        if let obj = try? JSONSerialization.jsonObject(with: data, options: []) {
            if let dict = obj as? [String: Any] {
                if let arr = dict["data"] as? [Any] {
                    return normalizeArray(arr)
                }
                if let arr = dict["list"] as? [Any] {
                    return normalizeArray(arr)
                }
                if let arr = dict["channels"] as? [Any] {
                    return normalizeArray(arr)
                }
            } else if let arr = obj as? [Any] {
                return normalizeArray(arr)
            }
        }
        return []
    }
    
    private func presentRoutePicker(channels: [Channel]) {
        routePopup?.removeFromSuperview()

        let popup = RoutePickerView(channels: channels)
        popup.delegate = self
        popup.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(popup)
        NSLayoutConstraint.activate([
            popup.topAnchor.constraint(equalTo: view.topAnchor),
            popup.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            popup.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            popup.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
        self.routePopup = popup
    }
    
    private func submitRoute(channel: Channel) {
        guard let url = URL(string: apiBaseURL + pathSetRoute) else {
            print("[Channel] Invalid setQudao URL")
            return
        }
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

//        let userId = String(UserDefaults.standard.object(forKey: "userId") as? Int ?? 0)
        let memberPhone = UserDefaults.standard.string(forKey: "memberPhone") ?? ""
        let memberIcon = UserDefaults.standard.string(forKey: "memberIconURL") ?? ""
        let memberName = UserDefaults.standard.string(forKey: "memberName") ?? memberPhone

        let phoneInfo: [String: Any] = [
            "systemName": UIDevice.current.systemName,
            "systemVersion": UIDevice.current.systemVersion,
            "model": deviceModel(),
            "localizedModel": UIDevice.current.localizedModel
        ]
        let phoneJsonString: String
        if let jsonData = try? JSONSerialization.data(withJSONObject: phoneInfo, options: []),
           let jsonString = String(data: jsonData, encoding: .utf8) {
            phoneJsonString = jsonString
        } else {
            phoneJsonString = "{}"
        }
        
        let body: [String: Any] = [
            "iosId": UIDevice.current.identifierForVendor?.uuidString ?? "",
            "alias": memberName,
            "phone": memberPhone,
            "brand": UIDevice.current.systemName,
            "model": deviceModel(),
            "appId": kTakuAppID,
            "deviceId": UIDevice.current.identifierForVendor?.uuidString ?? "",
            "iconUrl": memberIcon,
            "ditchId": Int64(channel.id) ?? 0,
            "phoneJson": phoneJsonString
        ]
        request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: [])

        if let body = request.httpBody,
           let bodyString = String(data: body, encoding: .utf8) {
            print("[Channel] setQudao Request URL: \(url)")
            print("[Channel] setQudao Request Headers: \(request.allHTTPHeaderFields ?? [:])")
            print("[Channel] setQudao Request Body: \(bodyString)")
        }

        showSystemOverlay()

        let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
            if let httpResponse = response as? HTTPURLResponse {
                print("[Channel] setQudao Response Code: \(httpResponse.statusCode)")
                print("[Channel] setQudao Response Headers: \(httpResponse.allHeaderFields)")
            }
            if let data = data, let responseString = String(data: data, encoding: .utf8) {
                print("[Channel] setQudao Response Body: \(responseString)")
            }

            if let data = data {
                do {
                    if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                        if let code = json["code"] as? Int, code != 200 {
                            let message = (json["message"] as? String) ?? (json["msg"] as? String) ?? "未知错误"
                            DispatchQueue.main.async { [weak self] in
                                self?.hideSystemOverlay()
                                self?.flashToast(message: message)
                            }
                            return
                        }
                    }
                } catch {
                    // Ignore JSON parse error here
                }
            }
            

            if let data = data,
               let obj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
               let code = obj["code"] as? Int, code == 200,
               let dataDict = obj["data"] as? [String: Any] {

                let nick = (dataDict["nickName"] as? String) ?? ""
                let roleId = (dataDict["userId"] as? String) ?? ""
                let todayCount: Int = {
                    if let v = dataDict["todayAnswerCount"] as? Int { return v }
                    if let s = dataDict["todayAnswerCount"] as? String, let i = Int(s) { return i }
                    return 0
                }()
                let historyCount: Int = {
                    if let v = dataDict["historyAnswerCount"] as? Int { return v }
                    if let s = dataDict["historyAnswerCount"] as? String, let i = Int(s) { return i }
                    return 0
                }()
                let registryTimeStr = (dataDict["registryTimeStr"] as? String) ?? ""
                let headImgURL = dataDict["headImg"] as? String
                let lastLoginTimeStr = (dataDict["lastLoginTimeStr"] as? String) ?? ""
                let powerValue: Int = {
                    if let v = dataDict["power"] as? Int { return v }
                    if let s = dataDict["power"] as? String, let i = Int(s) { return i }
                    return 0
                }()

                let lastQuestionId: String? = {
                    if let s = dataDict["lastQuestionId"] as? String, !s.isEmpty { return s }
                    if let n = dataDict["lastQuestionId"] as? NSNumber { return n.stringValue }
                    return nil
                }()

                let answerLogsFromLogin: [String] = {
                    if let arr = dataDict["answerRecordTimeList"] as? [String] { return arr }
                    if let anyArr = dataDict["answerRecordTimeList"] as? [Any] { return anyArr.compactMap { String(describing: $0) } }
                    return []
                }()

                DispatchQueue.main.async { [weak self] in
                    guard let self = self else { return }
                    self.hideSystemOverlay()

                    self.loginUserInfo = LoginUserInfo(
                        nickName: nick,
                        userId: roleId,
                        registryTimeStr: registryTimeStr,
                        todayAnswerCount: todayCount,
                        historyAnswerCount: historyCount,
                        headImgURL: headImgURL,
                        lastLoginTimeStr: lastLoginTimeStr,
                        answerLogs: answerLogsFromLogin
                    )

                    // Save to UserDefaults for backup
                    UserDefaults.standard.set(nick, forKey: "nickname")
                    UserDefaults.standard.set(roleId, forKey: "roleID")
                    UserDefaults.standard.set(registryTimeStr, forKey: "registryTimeStr")
                    UserDefaults.standard.set(todayCount, forKey: "todayAnswerCount")
                    UserDefaults.standard.set(historyCount, forKey: "historyAnswerCount")
                    UserDefaults.standard.set(headImgURL, forKey: "headImgURL")
                    UserDefaults.standard.set(lastLoginTimeStr, forKey: "lastLoginTimeStr")
                    UserDefaults.standard.set(powerValue, forKey: "power")
                    UserDefaults.standard.set(answerLogsFromLogin, forKey: "answerLogs")
                    if let lq = lastQuestionId { UserDefaults.standard.set(lq, forKey: "lastQuestionId") }
                    UserDefaults.standard.set(channel.name, forKey: "selectedChannelName")
                    UserDefaults.standard.synchronize()

                    DispatchQueue.main.async { [weak self] in
                        self?.flashToast(message: "登录成功")
                    }
                    // Navigate to Quiz
                    self.goToQuiz()
                }
            }

            if let error = error {
                print("[Channel] set error: \(error)")
                DispatchQueue.main.async { [weak self] in
                    self?.hideSystemOverlay()
                    self?.flashToast(message: "网络错误，请重试")
                }
                return
            }

            DispatchQueue.main.async {
                self?.hideSystemOverlay()
                self?.routePopup?.removeFromSuperview()
                self?.routePopup = nil
                print("[Channel] setQudao success for: \(channel.name) (id=\(channel.id))")
            }
        }
        task.resume()
    }
    
    
    private func goToQuiz() {
        let questionVC = QuizStageController()
        
        // 传递登录用户信息
        if let userInfo = loginUserInfo {
            questionVC.setLoginUserInfo(userInfo)
        }
        
        // 传递选择的渠道信息
        if let channel = selectedChannel {
            questionVC.setSelectedChannel(channel)
        }
        
        let navController = UINavigationController(rootViewController: questionVC)
        
        
        if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
            if let window = windowScene.windows.first {
                // 将 questionVC 作为 rootViewController
                window.rootViewController = navController
                window.makeKeyAndVisible()
            }
        }

        // Get current window and transition
//        guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
//            return
//        }
//        
//        window.rootViewController = questionVC
//        
//        UIView.transition(with: window,
//                          duration: 0.5,
//                          options: .transitionCrossDissolve,
//                          animations: nil,
//                          completion: nil)
    }
    
    private func refreshChannelTitle() {
        if let channel = selectedChannel {
            routeBtn.setTitle("\(channel.name) ▼", for: .normal)
        } else {
            routeBtn.setTitle("渠道 ▼", for: .normal)
        }
    }
    
    // MARK: - RoutePickerAgent
    func routePicker(_ panel: RoutePickerView, didPick channel: Channel) {
        selectedChannel = channel
        refreshChannelTitle()
        
        view.removeFromSuperview()
        routePopup = nil
        
        print("[Channel] Selected channel: \(channel.name) (id=\(channel.id))")
    }
    
    // MARK: - System Loading Helpers
    private func showSystemOverlay() {
        guard loadingOverlay == nil else { return }
        let overlay = UIView()
        overlay.translatesAutoresizingMaskIntoConstraints = false
        overlay.backgroundColor = UIColor.black.withAlphaComponent(0.35)
        overlay.isUserInteractionEnabled = true

        let spinner = UIActivityIndicatorView(style: .large)
        spinner.translatesAutoresizingMaskIntoConstraints = false
        spinner.startAnimating()
        spinner.hidesWhenStopped = true

        overlay.addSubview(spinner)
        view.addSubview(overlay)
        NSLayoutConstraint.activate([
            overlay.topAnchor.constraint(equalTo: view.topAnchor),
            overlay.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            overlay.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            overlay.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            spinner.centerXAnchor.constraint(equalTo: overlay.centerXAnchor),
            spinner.centerYAnchor.constraint(equalTo: overlay.centerYAnchor)
        ])

        loadingOverlay = overlay
        loadingSpinner = spinner
    }

    private func hideSystemOverlay() {
        loadingSpinner?.stopAnimating()
        loadingOverlay?.removeFromSuperview()
        loadingSpinner = nil
        loadingOverlay = nil
    }
    
    // MARK: - Toast Helper
    private func flashToast(message: String) {
        let tag = 9527
        if let existing = view.viewWithTag(tag) {
            existing.removeFromSuperview()
        }
        let toastLabel = UILabel()
        toastLabel.text = message
        toastLabel.font = UIFont.systemFont(ofSize: 15, weight: .medium)
        toastLabel.textColor = .white
        toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.8)
        toastLabel.textAlignment = .center
        toastLabel.alpha = 0.0
        toastLabel.layer.cornerRadius = 16
        toastLabel.clipsToBounds = true
        toastLabel.numberOfLines = 0
        toastLabel.tag = tag
        toastLabel.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(toastLabel)

        let horizontalPadding: CGFloat = 24
        let verticalPadding: CGFloat = 12
        let maxWidth = view.frame.width - 40
        let size = toastLabel.sizeThatFits(CGSize(width: maxWidth - horizontalPadding * 2, height: CGFloat.greatestFiniteMagnitude))
        let width = min(size.width + horizontalPadding * 2, maxWidth)
        let height = size.height + verticalPadding * 2

        NSLayoutConstraint.activate([
            toastLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            toastLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            toastLabel.widthAnchor.constraint(equalToConstant: width),
            toastLabel.heightAnchor.constraint(equalToConstant: height)
        ])
        UIView.animate(withDuration: 0.25, animations: {
            toastLabel.alpha = 1.0
        }) { _ in
            DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                UIView.animate(withDuration: 0.25, animations: {
                    toastLabel.alpha = 0.0
                }) { _ in
                    toastLabel.removeFromSuperview()
                }
            }
        }
    }
}
