import Foundation
import ComposeApp
import Combine

/// ViewModel for user profile management.
/// Observes DataManagerObservable for current user.
/// Calls APILayer directly for profile updates.
@MainActor
class ProfileViewModel: ObservableObject {
    // MARK: - Published Properties
    @Published var firstName: String = ""
    @Published var lastName: String = ""
    @Published var email: String = ""
    @Published var isLoading: Bool = false
    @Published var isLoadingUser: Bool = true
    @Published var errorMessage: String?
    @Published var successMessage: String?

    // MARK: - Private Properties
    private let tokenStorage: TokenStorageProtocol
    private let dataManager: DataManagerObservable
    private var cancellables = Set<AnyCancellable>()

    // MARK: - Initialization
    /// - Parameter dataManager: Observable cache the VM subscribes to.
    ///   Defaults to the shared singleton.
    init(
        tokenStorage: TokenStorageProtocol? = nil,
        dataManager: DataManagerObservable = .shared
    ) {
        self.tokenStorage = tokenStorage ?? Dependencies.current.makeTokenStorage()
        self.dataManager = dataManager

        // Seed from current cache so snapshot tests/previews render
        // populated state without waiting for Combine's async dispatch.
        if let user = dataManager.currentUser {
            self.firstName = user.firstName ?? ""
            self.lastName = user.lastName ?? ""
            self.email = user.email
            self.isLoadingUser = false
        }

        // Observe current user from injected DataManagerObservable
        dataManager.$currentUser
            .receive(on: DispatchQueue.main)
            .sink { [weak self] user in
                guard let self else { return }
                if let user = user {
                    self.firstName = user.firstName ?? ""
                    self.lastName = user.lastName ?? ""
                    self.email = user.email
                    self.isLoadingUser = false
                }
            }
            .store(in: &cancellables)

        // Load current user data
        loadCurrentUser()
    }

    // MARK: - Public Methods
    func loadCurrentUser() {
        guard tokenStorage.getToken() != nil else {
            errorMessage = "Not authenticated"
            isLoadingUser = false
            return
        }

        // Check if we already have user data
        if dataManager.currentUser != nil {
            isLoadingUser = false
            return
        }

        isLoadingUser = true
        errorMessage = nil

        Task {
            do {
                let result = try await APILayer.shared.getCurrentUser(forceRefresh: false)

                // DataManager is updated by APILayer, UI updates via Combine observation
                if result is ApiResultSuccess<User> {
                    self.isLoadingUser = false
                    self.errorMessage = nil
                } else if let error = ApiResultBridge.error(from: result) {
                    self.errorMessage = ErrorMessageParser.parse(error.message)
                    self.isLoadingUser = false
                } else {
                    self.errorMessage = "Failed to load profile"
                    self.isLoadingUser = false
                }
            } catch {
                self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
                self.isLoadingUser = false
            }
        }
    }

    func updateProfile() {
        guard !email.isEmpty else {
            errorMessage = "Email is required"
            return
        }

        guard let token = tokenStorage.getToken() else {
            errorMessage = "Not authenticated"
            return
        }

        isLoading = true
        errorMessage = nil
        successMessage = nil

        Task {
            do {
                let request = UpdateProfileRequest(
                    firstName: firstName.isEmpty ? nil : firstName,
                    lastName: lastName.isEmpty ? nil : lastName,
                    email: email
                )
                let result = try await APILayer.shared.updateProfile(token: token, request: request)

                // DataManager is updated by APILayer, UI updates via Combine observation
                if result is ApiResultSuccess<User> {
                    self.isLoading = false
                    self.errorMessage = nil
                    self.successMessage = "Profile updated successfully"
                } else if let error = ApiResultBridge.error(from: result) {
                    self.isLoading = false
                    self.errorMessage = ErrorMessageParser.parse(error.message)
                    self.successMessage = nil
                } else {
                    self.isLoading = false
                    self.errorMessage = "Failed to update profile"
                    self.successMessage = nil
                }
            } catch {
                self.isLoading = false
                self.errorMessage = ErrorMessageParser.parse(error.localizedDescription)
                self.successMessage = nil
            }
        }
    }

    func clearMessages() {
        errorMessage = nil
        successMessage = nil
    }
}
