import BuiltinExtension
import Foundation
import Preferences
import SuggestionBasic
import SuggestionProvider
import UserDefaultsObserver
import Workspace

public final class SuggestionServiceWorkspacePlugin: WorkspacePlugin {
    public typealias SuggestionServiceFactory = () -> any SuggestionServiceProvider
    let suggestionServiceFactory: SuggestionServiceFactory

    let suggestionFeatureUsabilityObserver = UserDefaultsObserver(
        object: UserDefaults.shared, forKeyPaths: [
            UserDefaultPreferenceKeys().suggestionFeatureEnabledProjectList.key,
            UserDefaultPreferenceKeys().disableSuggestionFeatureGlobally.key,
        ], context: nil
    )

    let providerChangeObserver = UserDefaultsObserver(
        object: UserDefaults.shared,
        forKeyPaths: [UserDefaultPreferenceKeys().suggestionFeatureProvider.key],
        context: nil
    )

    public var isRealtimeSuggestionEnabled: Bool {
        UserDefaults.shared.value(for: \.realtimeSuggestionToggle)
    }

    private var _suggestionService: SuggestionServiceProvider?

    public var suggestionService: SuggestionServiceProvider? {
        // Check if the workspace is disabled.
        let isSuggestionDisabledGlobally = UserDefaults.shared
            .value(for: \.disableSuggestionFeatureGlobally)
        if isSuggestionDisabledGlobally {
            let enabledList = UserDefaults.shared.value(for: \.suggestionFeatureEnabledProjectList)
            if !enabledList.contains(where: { path in projectRootURL.path.hasPrefix(path) }) {
                // If it's disable, remove the service
                _suggestionService = nil
                return nil
            }
        }

        if _suggestionService == nil {
            _suggestionService = suggestionServiceFactory()
        }
        return _suggestionService
    }

    public var isSuggestionFeatureEnabled: Bool {
        let isSuggestionDisabledGlobally = UserDefaults.shared
            .value(for: \.disableSuggestionFeatureGlobally)
        if isSuggestionDisabledGlobally {
            let enabledList = UserDefaults.shared.value(for: \.suggestionFeatureEnabledProjectList)
            if !enabledList.contains(where: { path in projectRootURL.path.hasPrefix(path) }) {
                return false
            }
        }
        return true
    }

    public init(
        workspace: Workspace,
        suggestionProviderFactory: @escaping SuggestionServiceFactory
    ) {
        suggestionServiceFactory = suggestionProviderFactory
        super.init(workspace: workspace)

        suggestionFeatureUsabilityObserver.onChange = { [weak self] in
            guard let self else { return }
            _ = self.suggestionService
        }

        providerChangeObserver.onChange = { [weak self] in
            guard let self else { return }
            self._suggestionService = nil
        }
    }

    func notifyAccepted(_ suggestion: CodeSuggestion) async {
        await suggestionService?.notifyAccepted(
            suggestion,
            workspaceInfo: .init(workspaceURL: workspaceURL, projectURL: projectRootURL)
        )
    }

    func notifyRejected(_ suggestions: [CodeSuggestion]) async {
        await suggestionService?.notifyRejected(
            suggestions,
            workspaceInfo: .init(workspaceURL: workspaceURL, projectURL: projectRootURL)
        )
    }
}

