//
//  TooltipManager.swift
//  lichunWebsocket
//
//  Manages contextual tooltips for first-time user experiences
//

import SwiftUI
import Combine

// MARK: - Models

/// Represents a tooltip with its content and positioning
struct TooltipData: Identifiable {
    let id: String
    let title: String
    let message: String
    let position: TooltipPosition
}

/// Defines where the tooltip should be positioned relative to its target
enum TooltipPosition {
    case top
    case bottom
    case leading
    case trailing
}

/// Defines when a tooltip should be triggered
enum TooltipTrigger {
    case onAppear      // Show when view appears
    case onTap         // Show when user taps
    case manual        // Controlled programmatically
}

// MARK: - TooltipManager

/// Manages the display and tracking of contextual tooltips throughout the app
class TooltipManager: ObservableObject {

    // MARK: - Published Properties

    /// The currently active tooltip being displayed
    @Published var activeTooltip: TooltipData?

    // MARK: - Private Properties

    /// Set of tooltip IDs that have been seen by the user
    private var tooltipsSeen: Set<String> = []

    /// UserDefaults key for persisting seen tooltips
    private let tooltipsSeenKey = "tooltipsSeen"

    /// Optional WebSocketService for analytics
    private weak var webSocketService: WebSocketService?

    // MARK: - Initialization

    init(webSocketService: WebSocketService? = nil) {
        self.webSocketService = webSocketService
        loadTooltipsSeen()
    }

    // MARK: - Public Methods

    /// Shows a tooltip if it hasn't been seen before
    /// - Parameters:
    ///   - id: Unique identifier for the tooltip
    ///   - title: Bold title text
    ///   - message: Descriptive message text
    ///   - position: Where to position the tooltip relative to target
    func showTooltipIfNeeded(_ id: String, title: String, message: String, position: TooltipPosition = .top) {
        guard !tooltipsSeen.contains(id) else { return }

        let tooltip = TooltipData(
            id: id,
            title: title,
            message: message,
            position: position
        )

        withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
            activeTooltip = tooltip
        }
    }

    /// Dismisses the current tooltip and marks it as seen
    func dismissTooltip() {
        guard let tooltip = activeTooltip else { return }

        // Mark as seen
        tooltipsSeen.insert(tooltip.id)
        saveTooltipsSeen()

        // Send analytics to server if available
        sendTooltipSeenToServer(tooltipId: tooltip.id)

        // Clear active tooltip
        withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
            activeTooltip = nil
        }
    }

    /// Checks if a tooltip has been seen
    /// - Parameter id: The tooltip identifier
    /// - Returns: True if the tooltip has been seen
    func hasSeenTooltip(_ id: String) -> Bool {
        return tooltipsSeen.contains(id)
    }

    /// Resets all tooltips (useful for testing or user preference)
    func resetAllTooltips() {
        tooltipsSeen.removeAll()
        saveTooltipsSeen()
        activeTooltip = nil
    }

    /// Resets a specific tooltip
    /// - Parameter id: The tooltip identifier to reset
    func resetTooltip(_ id: String) {
        tooltipsSeen.remove(id)
        saveTooltipsSeen()
    }

    // MARK: - Private Methods

    /// Loads seen tooltips from UserDefaults
    private func loadTooltipsSeen() {
        if let savedTooltips = UserDefaults.standard.array(forKey: tooltipsSeenKey) as? [String] {
            tooltipsSeen = Set(savedTooltips)
        }
    }

    /// Saves seen tooltips to UserDefaults
    private func saveTooltipsSeen() {
        let tooltipsArray = Array(tooltipsSeen)
        UserDefaults.standard.set(tooltipsArray, forKey: tooltipsSeenKey)
    }

    /// Sends tooltip seen event to server for analytics
    /// - Parameter tooltipId: The tooltip identifier
    private func sendTooltipSeenToServer(tooltipId: String) {
        guard let webSocketService = webSocketService else { return }

        webSocketService.sendMessage(message: WebSocketCommands.tooltipSeen(tooltipId: tooltipId))
    }
}
