//
//  ToastCenter.swift
//  suixinkan
//
//  Created by Codex on 2026/6/18.
//

import Combine
import SwiftUI
import UIKit

@MainActor
/// 全局 Toast 状态中心，负责保存和清除当前提示文案。
final class ToastCenter: ObservableObject {
    @Published fileprivate var message: String?
    private let autoDismissNanoseconds: UInt64
    @Published private var dismissTask: Task<Void, Never>?
    @Published private var displayToken: UInt64 = 0

    /// 创建 Toast 状态中心，默认 2.2 秒后自动隐藏。
    init(autoDismissNanoseconds: UInt64 = 2_200_000_000) {
        self.autoDismissNanoseconds = autoDismissNanoseconds
    }

    /// 显示一条全局 Toast 文案。
    func show(_ message: String) {
        displayToken &+= 1
        self.message = message
        scheduleAutoDismiss(token: displayToken)
    }

    /// 清除当前 Toast 文案。
    func dismiss() {
        displayToken &+= 1
        dismissTask?.cancel()
        dismissTask = nil
        message = nil
    }

    /// 为当前 Toast 安排自动隐藏任务，并避免旧任务误清除新 Toast。
    private func scheduleAutoDismiss(token: UInt64) {
        dismissTask?.cancel()
        let delay = autoDismissNanoseconds
        dismissTask = Task { [weak self] in
            do {
                try await Task.sleep(nanoseconds: delay)
            } catch {
                return
            }
            await MainActor.run {
                guard let self, self.displayToken == token else { return }
                self.message = nil
                self.dismissTask = nil
            }
        }
    }

    #if DEBUG
    /// 测试专用快照，业务代码不应读取 Toast 展示状态。
    var snapshotForTests: ToastSnapshot {
        ToastSnapshot(message: message)
    }
    #endif
}

/// Toast 独立窗口宿主，确保提示浮在 sheet / fullScreenCover 等 present 层之上。
@MainActor
private final class ToastWindowPresenter {
    static let shared = ToastWindowPresenter()

    private var toastWindow: UIWindow?

    /// 在独立 UIWindow 中展示 Toast。
    func show(message: String) {
        guard let windowScene = resolveWindowScene() else { return }

        let window: UIWindow
        if let existing = toastWindow, existing.windowScene === windowScene {
            window = existing
        } else {
            let newWindow = PassthroughWindow(windowScene: windowScene)
            newWindow.windowLevel = .alert + 1
            newWindow.backgroundColor = .clear
            toastWindow = newWindow
            window = newWindow
        }

        let hosting = UIHostingController(
            rootView: ToastBannerHostView(message: message)
        )
        hosting.view.backgroundColor = .clear
        window.rootViewController = hosting
        window.isHidden = false
    }

    /// 隐藏 Toast 窗口。
    func hide() {
        toastWindow?.isHidden = true
        toastWindow?.rootViewController = nil
    }

    /// 取当前前台 window scene，供独立 Toast 窗口挂载。
    private func resolveWindowScene() -> UIWindowScene? {
        let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
        return scenes.first { $0.activationState == .foregroundActive } ?? scenes.first
    }
}

/// 透传触摸事件的 Toast 窗口，避免挡住下层弹窗交互。
private final class PassthroughWindow: UIWindow {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard let view = super.hitTest(point, with: event) else { return nil }
        return view === rootViewController?.view ? nil : view
    }
}

/// Toast 全屏居中容器。
private struct ToastBannerHostView: View {
    let message: String

    var body: some View {
        ZStack {
            ToastBannerContent(message: message)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .allowsHitTesting(false)
    }
}

/// 屏幕中央的黑色半透明圆角 Toast 卡片。
private struct ToastBannerContent: View {
    let message: String

    var body: some View {
        HStack(spacing: 10) {
            Image(systemName: "exclamationmark.triangle.fill")
                .font(.system(size: 16, weight: .semibold))

            Text(message)
                .font(.system(size: 16, weight: .medium))
                .lineLimit(3)
                .multilineTextAlignment(.leading)
                .fixedSize(horizontal: false, vertical: true)
        }
        .foregroundStyle(.white)
        .padding(.horizontal, 20)
        .padding(.vertical, 14)
        .background(Color.black.opacity(0.78), in: RoundedRectangle(cornerRadius: 12))
        .padding(.horizontal, 40)
        .accessibilityIdentifier("global.toast")
    }
}

/// 全局 Toast 展示桥接层，监听 ToastCenter 并驱动独立窗口。
private struct GlobalToastOverlay: ViewModifier {
    @EnvironmentObject private var toastCenter: ToastCenter

    func body(content: Content) -> some View {
        content
            .onAppear {
                syncToastWindow(with: toastCenter.message)
            }
            .onChange(of: toastCenter.message) { message in
                syncToastWindow(with: message)
            }
    }

    /// 根据当前文案显示或隐藏 Toast 窗口。
    private func syncToastWindow(with message: String?) {
        if let message {
            ToastWindowPresenter.shared.show(message: message)
        } else {
            ToastWindowPresenter.shared.hide()
        }
    }
}

#if DEBUG
/// 全局 Toast 测试快照，用于验证文案和自动隐藏行为。
struct ToastSnapshot: Equatable {
    let message: String?
}
#endif

extension View {
    /// 给任意根视图追加全局 Toast 展示能力。
    func globalToastOverlay() -> some View {
        modifier(GlobalToastOverlay())
    }
}
